DP
1. 피보나치 수열 (Fibonacci Sequence)
Bottom-up 방식 (반복문 사용)
public int fibonacci(int n) {
if (n <= 1) return 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];
}
Top-down 방식 (메모이제이션 사용)
public int fibonacci(int n, int[] memo) {
if (n <= 1) return n;
if (memo[n] != 0) return memo[n]; // 이미 계산된 값이 있으면 사용
memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo); // 결과 저장
return memo[n];
}
2. 0/1 배낭 문제 (Knapsack Problem)
public int knapsack(int W, int[] weights, int[] values, int n) {
int[][] dp = new int[n + 1][W + 1];
for (int i = 1; i <= n; i++) {
for (int w = 1; w <= W; w++) {
if (weights[i - 1] <= w) {
dp[i][w] = Math.max(values[i - 1] + dp[i - 1][w - weights[i - 1]], dp[i - 1][w]);
} else {
dp[i][w] = dp[i - 1][w];
}
}
}
return dp[n][W]; // 최대 가치 반환
}
3. 계단 오르기 문제 (Climbing Stairs)
public int climbStairs(int n) {
if (n == 1) return 1;
int[] dp = new int[n + 1];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) {
dp[i] = dp[i - 1] + dp[i - 2]; // i-1 계단과 i-2 계단에서 오는 경우의 합
}
return dp[n];
}
4. 최장 증가 부분 수열 (LIS, Longest Increasing Subsequence)
public int lengthOfLIS(int[] nums) {
if (nums == null || nums.length == 0) return 0;
int n = nums.length;
int[] dp = new int[n];
Arrays.fill(dp, 1);
int maxLen = 1;
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dp[i] = Math.max(dp[i], dp[j] + 1);
}
}
maxLen = Math.max(maxLen, dp[i]);
}
return maxLen;
}
5. 동전 거스름돈 문제 (Coin Change)
최소 동전 개수 문제
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1); // 임의의 큰 값으로 초기화
dp[0] = 0;
for (int coin : coins) {
for (int i = coin; i <= amount; i++) {
dp[i] = Math.min(dp[i], dp[i - coin] + 1);
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
6. 최대 부분 배열 합 (Kadane's Algorithm)
public int maxSubArray(int[] nums) {
int maxSum = nums[0];
int currentSum = nums[0];
for (int i = 1; i < nums.length; i++) {
currentSum = Math.max(nums[i], currentSum + nums[i]);
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}
7. 집 도색 문제 (House Painting Problem)
public int minCost(int[][] costs) {
if (costs == null || costs.length == 0) return 0;
for (int i = 1; i < costs.length; i++) {
costs[i][0] += Math.min(costs[i - 1][1], costs[i - 1][2]);
costs[i][1] += Math.min(costs[i - 1][0], costs[i - 1][2]);
costs[i][2] += Math.min(costs[i - 1][0], costs[i - 1][1]);
}
int n = costs.length - 1;
return Math.min(Math.min(costs[n][0], costs[n][1]), costs[n][2]);
}
8. 문자열 간의 최소 편집 거리 (Edit Distance)
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0) {
dp[i][j] = j;
} else if (j == 0) {
dp[i][j] = i;
} else if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = 1 + Math.min(dp[i - 1][j - 1], Math.min(dp[i - 1][j], dp[i][j - 1]));
}
}
}
return dp[m][n];
}
9. 연속된 숫자의 곱 최대값 (Maximum Product Subarray)
public int maxProduct(int[] nums) {
int maxProduct = nums[0], minProduct = nums[0], result = nums[0];
for (int i = 1; i < nums.length; i++) {
if (nums[i] < 0) {
int temp = maxProduct;
maxProduct = minProduct;
minProduct = temp;
}
maxProduct = Math.max(nums[i], maxProduct * nums[i]);
minProduct = Math.min(nums[i], minProduct * nums[i]);
result = Math.max(result, maxProduct);
}
return result;
}
Last updated