큰 문제를 작은 문제 단위로 해소해 나가는 것
// 문제: 피보나치 수열의 n번째 항을 구하는 함수를 작성하세요.
// 재귀가 아닌 반복을 이용 : O(n) 시간, 공간 복잡도
public int Fibonacci(int n)
{
int[] dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i <= n; i++)
{
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
// 문제: 주어진 동전들로 특정 금액을 만드는데 필요한 최소 동전 수를 구하는 함수를 작성하세요.
public int MinCoins(int[] coins, int amount)
{
Array.Sort(coins);
int count = 0;
for(int i = coins.Length - 1; i >= 0; i--)
{
while(amount >= coins[i])
{
amount -= coins[i];
count++;
}
}
if(amount > 0) return -1;
return count;
}
중간 tip
큰 문제를 파악할 때, 먼저 문제를 분석하고 작은 문제로 나누는 것이 중요.
작은 문제로 나누고 나서 어떻게 규칙성을 만들지 생각할 것.
작은 부분부터 해결
작은 문제로 소분했는데 데이터가 더 필요하다 -> 동적 프로그래밍
해소가 되고 다음 해소도 동일한 방식이다 -> 분할 정복
// 문제: 주어진 배열을 정렬하는 함수를 작성하세요. (퀵 정렬 사용)
public void QuickSort(int[] arr, int low, int high)
{
if(low < high)
{
int pi = Partition(arr, low, high);
QuickSort(arr, low, pi - 1); // Before pi
QuickSort(arr, pi + 1, high); // After pi
}
}
int Partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = (low - 1);
for(int j = low; j <= high - 1; j++)
{
if(arr[j] < pivot)
{
i++;
Swap(arr, i, j);
}
}
Swap(arr, i + 1, high);
return (i + 1);
}
void Swap(int[] arr, int a, int b)
{
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
tip
큰 문제를 만나서 문제를 소분하고 나서 어떻게 풀어나갈지 생각할 때,
첫 시작점에서 위의 방식 세 개 중에 어떤 것이 좋을지 생각해보기