[알고리즘] 다이나믹 프로그래밍 (feat. Leetcode)

2022. 2. 6. 16:03·Engineering/Algorithm

다이나믹 프로그래밍이란?


큰 문제를 작은 문제로 나누어 풀고, 작은 문제의 답을 재활용하는 기법을 의미한다.

메모리 비용을 활용하여 시간적 비용을 줄이는 방식이다.

 

👉 조건

  1. 부분 반복 문제: 작은 문제가 반복되는 경우
  2. 최적 부분 구조: 같은 문제는 구할 때마다 정답이 같을 경우

작은 문제가 반복되고 그 문제의 답이 같기 때문에, 굳이 작은 문제에 대한 계산을 반복하지 않고 이를 메모리에 저장하여 활용하는 것이다.

 

 

Fibonacci 수열


DP를 설명할 때 가장 기본적으로 예를 들 수 있는 것이 Fibonacci 수열이다. 이는 f(n) = f(n-1) + f(n-2)의 점화식을 가진다. 

아래 Leetcode 문제를 재귀 함수를 이용하는 방법과 동적 프로그래밍을 사용하는 방법으로 풀어볼 것이다. 

https://leetcode.com/problems/fibonacci-number/

 

Fibonacci Number - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

 

1️⃣ 재귀함수 사용

def fib(self, n):
    def fibo(n):
        if n == 1:
            return 1
        elif n == 2:
            return 1
        else:
            return fibo(n-1) + fibo(n-2)

    return fibo(n)

위 코드를 도식화한 이미지

 

재귀 함수로 풀게 되면 간단하게 풀 수 있지만, 위의 그림에서 확인할 수 있듯이 호출되는 함수의 수가 기하급수적으로 증가한다.

해당 코드를 제출하게 되면 아래와 같이 Runtime Error가 나타난다. 😥 

 

 

2️⃣ 동적 프로그래밍 사용

💡 이 문제를 DP로 풀 수 있지 않을까? 위의 조건을 생각해보자

  1. 부분 반복 문제
    fib(7)을 구하기 위해서는 fib(6)와 fib(5)가 필요하다. 그리고 fib(6)을 구하기 위해서는 fib(5)와 fib(6)이 필요하다. 이 경우 살펴보면 fib(7)과 fib(6)에서 fib(5)가 반복된다. 즉, 작은 문제가 반복되는 구조라고 볼 수 있다.

  2. 최적 부분 구조
    fibo 수열의 경우 1번째/2번째 수는 각각 1로 고정되어 있으며 3번째 수열은 언제나 결과가 2이다. 그 이후로도 이전의 두 개의 값을 더하여 계산함으로 fibo 수열에서 어떤 수를 구할 때나 수열의 값이 같다.

 

방법

  1. 모든 작은 문제들은 한번만 푼다. 이를 위해 정답을 구한 작은 문제의 결과는 어딘가 저장한다.
  2. 다시 그보다 큰 문제를 풀어나갈 때 똑같은 문제가 나타나면 앞서 저장한 결과 값을 이용한다.

 

def fib(self, n):
    fibo = [None,1,1]

    if n < 3:
        return fibo[n]

    for i in range(3, n+1):
        fibo.append(fibo[i-1] + fibo[i-2])

    return fibo[n]

성공!

 

 

Bottom-up과 Top-down


  1. Bottom-up
    • 작은 문제부터 차근차근 구해나가는 방법이다.
    • 소스의 가독성이 저하될 수 있다.

  2. Top-down
    • 큰 문제를 풀다가 작은 문제가 아직 풀리지 않았다면 그때 작은 문제를 해결한다. 재귀 함수로 구현하는 경우 대부분 Top-down이다.
    • 소스의 가독성이 증가하지만, 작성이 조금 어렵다.

 

 

 

참고
https://galid1.tistory.com/507
https://kyun2da.github.io/2020/01/19/DynamicProgramming/

 

'Engineering > Algorithm' 카테고리의 다른 글

[프로그래머스/Python] 경주로 건설  (0) 2022.03.25
[Algorithm] 정렬 알고리즘 간단 정리와 Python 구현 (버블정렬, 선택정렬, 퀵정렬, 병합정렬, 힙정렬)  (0) 2022.02.21
[자료구조] 힙 (Heaps)  (0) 2022.02.05
[자료구조] Binary Search Tree  (0) 2022.02.05
[Leetcode/Python] 5. Longest Palindromic Substring  (0) 2022.01.12
'Engineering/Algorithm' 카테고리의 다른 글
  • [프로그래머스/Python] 경주로 건설
  • [Algorithm] 정렬 알고리즘 간단 정리와 Python 구현 (버블정렬, 선택정렬, 퀵정렬, 병합정렬, 힙정렬)
  • [자료구조] 힙 (Heaps)
  • [자료구조] Binary Search Tree
AI건축가
AI건축가
LLMOps Engineer로 커리어를 쌓고 있습니다. 저만의 시점으로 AI를 해석하고자 노력합니다. 함께 배우고 성장하는 공간이 되었으면 좋겠습니다. 😊🚀
  • AI건축가
    DeepFlame AI
    AI건축가
  • 전체
    오늘
    어제
    • 분류 전체보기
      • AI
      • Ops
      • Engineering
        • Algorithm
        • CS
        • BigData
        • Tools
      • Personal
        • Toy Project
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    mlops
    algorithm
    DP
    Bio
    deepseek
    Python
    세미나
    db
    MSA
    PostgreSQL
    hadoop
    scala
    airflow
    Cloud
    ec2
    kubernetes
    Hive
    AWS
    LeetCode
    mongoDB
    Ai
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
AI건축가
[알고리즘] 다이나믹 프로그래밍 (feat. Leetcode)
상단으로

티스토리툴바