동적계획법 활용: 돌 무게 최소화, 목표 합 계산, 0과 1의 조합 최대화

1049. 마지막 돌의 무게 II

이 문제는 돌들을 두 그룹으로 나누어 각각 충돌했을 때 남는 돌의 무게를 최소화하는 것이 목적이다. 이는 0-1 배낭 문제로 변환할 수 있다.

각 돌의 무게와 가치는 동일하게 설정하며, 총 무게의 절반을 목표로 하는 배낭 용량을 정한다.

일차원 배열 버전


class Solution {
    public int lastStoneWeightII(int[] stones) {
        int totalWeight = Arrays.stream(stones).sum();
        int target = totalWeight / 2;
        int[] dp = new int[target + 1];
        
        for (int stone : stones) {
            for (int j = target; j >= stone; j--) {
                dp[j] = Math.max(dp[j], dp[j - stone] + stone);
            }
        }
        
        return totalWeight - 2 * dp[target];
    }
}
  • 시간 복잡도: O(n × m), n은 돌 개수, m은 총 무게의 절반
  • 공간 복잡도: O(m)

이차원 배열 버전


class Solution {
    public int lastStoneWeightII(int[] stones) {
        int totalWeight = 0;
        for (int stone : stones) totalWeight += stone;
        int target = totalWeight / 2;
        
        int[][] dp = new int[stones.length][target + 1];
        
        // 초기화: 첫 번째 돌에 대해 가능한 경우
        for (int j = stones[0]; j <= target; j++) {
            dp[0][j] = stones[0];
        }
        
        for (int i = 1; i < stones.length; i++) {
            for (int j = 1; j <= target; j++) {
                if (j >= stones[i]) {
                    dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j - stones[i]] + stones[i]);
                } else {
                    dp[i][j] = dp[i-1][j];
                }
            }
        }
        
        return totalWeight - 2 * dp[stones.length - 1][target];
    }
}

494. 목표 합계

배열 내 요소에 + 또는 - 부호를 붙여 전체 합이 특정 값이 되도록 만드는 방법의 수를 구하는 문제다. 이를 0-1 배낭 문제로 해석하면, 양수 부분의 합을 정해두고 해당 배낭을 채우는 방법의 수를 계산하면 된다.

결과적으로, left = (sum + target) / 2 를 구하고, 이 값을 배낭 용량으로 삼아 가능한 조합 수를 세면 된다.

이차원 배열 버전


class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int sum = Arrays.stream(nums).sum();
        if (Math.abs(target) > sum || (sum + target) % 2 == 1) return 0;
        
        int bagSize = (sum + target) / 2;
        int[][] dp = new int[nums.length][bagSize + 1];
        
        // 초기화: 0번 인덱스 처리
        if (nums[0] <= bagSize) dp[0][nums[0]] = 1;
        
        int zeroCount = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 0) zeroCount++;
            dp[i][0] = (int) Math.pow(2, zeroCount);
        }
        
        for (int i = 1; i < nums.length; i++) {
            for (int j = 1; j <= bagSize; j++) {
                if (nums[i] > j) {
                    dp[i][j] = dp[i-1][j];
                } else {
                    dp[i][j] = dp[i-1][j] + dp[i-1][j - nums[i]];
                }
            }
        }
        
        return dp[nums.length - 1][bagSize];
    }
}

일차원 배열 버전


class Solution {
    public int findTargetSumWays(int[] nums, int target) {
        int sum = Arrays.stream(nums).sum();
        if (Math.abs(target) > sum || (sum + target) % 2 == 1) return 0;
        
        int bagSize = (sum + target) / 2;
        int[] dp = new int[bagSize + 1];
        dp[0] = 1;
        
        for (int num : nums) {
            for (int j = bagSize; j >= num; j--) {
                dp[j] += dp[j - num];
            }
        }
        
        return dp[bagSize];
    }
}
  • 시간 복잡도: O(n × m), n은 요소 수, m은 배낭 용량
  • 공간 복잡도: O(m)

474. 0과 1의 개수

문자열 배열에서 각 문자열의 0과 1 개수를 고려하여, 총 0개수가 ≤ m, 1개수가 ≤ n인 최대 서브셋 크기를 찾는 문제다.

이는 두 가지 제약 조건이 있는 0-1 배낭 문제로 간주할 수 있으며, 각 문자열은 물체, 0과 1의 개수는 무게로 취급된다.

이차원 배열 해결법


class Solution {
    public int findMaxForm(String[] strs, int m, int n) {
        int[][] dp = new int[m + 1][n + 1];
        
        for (String str : strs) {
            int zeros = 0, ones = 0;
            for (char c : str.toCharArray()) {
                if (c == '0') zeros++;
                else ones++;
            }
            
            for (int i = m; i >= zeros; i--) {
                for (int j = n; j >= ones; j--) {
                    dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones] + 1);
                }
            }
        }
        
        return dp[m][n];
    }
}
  • 시간 복잡도: O(k × m × n), k는 문자열 개수
  • 공간 복잡도: O(m × n)

태그: 동적계획법 0-1배낭문제 일차원배열 이차원배열 조합수세기

6월 21일 02:02에 게시됨