[알고리즘] 동적 프로그래밍

2022. 12. 12. 12:08·개발/자료구조
728x90
반응형

1. 동적프로그래밍

문제를 더 작은 조각으로 나눈 다음에 앞에 위치한 조각을 기억하는것을 통해서

해야하는 작업의 양을 줄이는 방식으로 문제를 푸는 접근법이다.

 

사용 조건

최적 부분구조가 존재하는지, 반복되는 하위 문제가 있는지를 확인하고 사용할 수 있다.

문제에 어떤방식으로든 중첩되는 하위 문제들이 있어야 한다.

이 말은 한문제를 더 작은 문제들로 나눌수 있고 그 조각들중 일부가 재활용이 가능하다는 말이다.

 

최적부분 구조

하위 문제의 최적 해답을 통해서 더 큰 범주의 문제의 최적 해답을

구성할 수 있는 경우 해당 문제가 최적 부분 구조를 가진다고 한다.

예시) 피보나치 수열은 5번째의 수를 찾기 위해 4번째수와 3번째수를 이용한다.

 

2. 피보나치

function fib(n) {
  if (n <= 2) return 1;
  return fib(n - 1) + fib(n - 2);
}

피보나치 수열은 위와 같이 코드를 짤수 있다.

피보나치 수열은 각각의 값을 구하기 위해 전의 값들을 계속 계산해야 한다.

위 피보나치 코드의 시간복잡도는 O(2^n)으로 굉장히 나쁘다.

피보나치 수열은 중첩되는 하위 문제들이 존재하기 때문에 동적프로그래밍의 좋은 예시이다.

 

3. 동적프로그래밍

예전의 값을 기억했다가 어떻게든 저장을 해서 각 하위 문제를 풀때 다시 확인하면 복잡한 계산을 건너뛸수 있다.

(1) 메모이제이션(memoization)

보통 배열이나 객체인 데이터를 저장할 구조를 만든 다음에 하위 문제를 풀고 그 값을 저장해 둔다.

function fib(n, memo = []) {
  if (memo[n] !== undefined) return memo[n];
  if (n <= 2) return 1;
  let res = fib(n - 1, memo) + fib(n - 2, memo);
  memo[n] = res;
  return res;
}

위 코드로 시간복잡도를 O(n)까지 줄일 수 있다.

동적 프로그래밍의 핵심은 한문제를 풀때 그 문제를 더 작은 하위 문제들로 나누고

각각을 한번 이상 풀어야 할때 앞에서 계산한 값을 저장해서 같은 하위문제를 다시 풀지 않는것이다.

 

(2) 타뷸레이션(tabulation)

보통 루프와 같이 순환을 통해서 작업을한다.

가장 작은 하위 문제를 푼 다음에 그 결과를 테이블에 저장한다.

function fib(n) {
  if (n <= 2) return 1;
  let fibNums = [0, 1, 1];
  for (let i = 3; i <= n; i++) {
    fibNums[i] = fibNums[i - 1] + fibNums[i - 2];
  }
  return fibNums[n];
}

(3) 두 접근법의 차이점

메모이제이션은 재귀를 사용했기 때문에 공간적 제약을 받는다.

만약 10000번째의 피보나치 수열을 알고싶을때 메모이제이션 방법을 사용하게 된다면

콜스택 사이즈를 초과했다는 오류를 볼수 있다.

하지만 타뷸레이션은 재귀를 사용하지 않기 때문에 공간적 제약을 받지 않는다.

따라서 타뷸레이션은 원활하게 코드를 실행할 수 있다.

4. 프로그래머스 문제

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

이전의 값들을 기억해서 계속 사용해야 하는 문제이다.

이 문제는 동적프로그래밍으로 접근이 가능하다.

function solution(land) {
    const length = land.length
    for(let i = 1 ; i<length; i++){
        land[i][0] += Math.max(land[i-1][1],land[i-1][2],land[i-1][3])
        land[i][1] += Math.max(land[i-1][0],land[i-1][2],land[i-1][3])
        land[i][2] += Math.max(land[i-1][0],land[i-1][1],land[i-1][3])
        land[i][3] += Math.max(land[i-1][0],land[i-1][1],land[i-1][2])
    }
    return Math.max(...land[length-1]);
}

 

728x90
반응형

'개발 > 자료구조' 카테고리의 다른 글

[자료구조] 다익스트라 알고리즘 (길찾기)  (0) 2022.12.12
[자료구조] 그래프  (1) 2022.12.08
[자료구조] 해시테이블  (0) 2022.12.06
[자료구조] 우선순위큐  (0) 2022.12.06
[자료구조] 이진힙 - BinaryHeap  (0) 2022.12.02
'개발/자료구조' 카테고리의 다른 글
  • [자료구조] 다익스트라 알고리즘 (길찾기)
  • [자료구조] 그래프
  • [자료구조] 해시테이블
  • [자료구조] 우선순위큐
TeTedo.
TeTedo.
  • TeTedo.
    TeTedo 개발 일기
    TeTedo.
  • 전체
    오늘
    어제
    • 분류 전체보기 (319)
      • 개발 (274)
        • Article (4)
        • 정리 (21)
        • Spring Boot (17)
        • JPA (2)
        • JAVA (6)
        • Database (4)
        • 자료구조 (11)
        • 알고리즘 (32)
        • React (20)
        • Docker (10)
        • node.js (18)
        • Devops (11)
        • Linux (4)
        • TypeScript (3)
        • Go (10)
        • HyperLedger (4)
        • BlockChain (43)
        • html, css, js (48)
        • CS (3)
        • AWS (3)
      • 모아두고 나중에 쓰기 (3)
      • 팀프로젝트 (18)
        • SNS(키보드워리어) (9)
        • close_sea (9)
      • 개인프로젝트 (1)
        • Around Flavor (1)
        • CHAM (13)
        • ethFruitShop (5)
      • 독서 (0)
        • 스프링부트와 AWS로 혼자 구현하는 웹 서비스 (0)
  • 블로그 메뉴

    • 홈
    • 개발일기
    • CS
    • 실습
    • 코딩테스트
    • 웹
    • Go
    • node.js
    • 팀플
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    하이퍼레저
    명령어
    html
    node
    프로그래머스
    ERC721
    mysql
    erc20
    CSS
    30일챌린지
    js
    go언어
    도커
    컨테이너
    블록체인
    nodejs
    node.js
    go
    React
    30일 챌린지
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
TeTedo.
[알고리즘] 동적 프로그래밍
상단으로

티스토리툴바