알고리즘/LeetCode

[LeetCode] 377. Combination Sum IV - Java

반응형

https://leetcode.com/problems/combination-sum-iv/description/

 

Combination Sum IV - 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


문제

Given an array of distinct integers nums and a target integer target, return the number of possible combinations that add up to target.

The test cases are generated so that the answer can fit in a 32-bit integer.

 

Example 1:

Input: nums = [1,2,3], target = 4
Output: 7
Explanation:
The possible combination ways are:
(1, 1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 3)
(2, 1, 1)
(2, 2)
(3, 1)
Note that different sequences are counted as different combinations.

Example 2:

Input: nums = [9], target = 3
Output: 0

 

Constraints:

  • 1 <= nums.length <= 200
  • 1 <= nums[i] <= 1000
  • All the elements of nums are unique.
  • 1 <= target <= 1000

 

Follow up: What if negative numbers are allowed in the given array? How does it change the problem? What limitation we need to add to the question to allow negative numbers?


풀이

풀이 과정

정수 배열 nums와 정수 target이 주어졌을 때 nums배열의 값들로 target을 만들 수 있는 경우의 수를 구해야한다.
이 때 순서가 다른 경우의 수는 각각 다른 경우로 판단한다.

동적 계획법을 이용하여 0부터 target까지 만들 수 있는 경우의 수를 탐색한다.

0부터 target까지 각 인덱스 n에 대하여 n을 만들 수 있는 경우의 수를 저장할 정수 배열을 선언하고, 0을 만드는 경우의 수는 한 가지이므로 0번째 인덱스를 1로 초기화한다.

// 각 인덱스 n에 대하여 n을 만들 수 있는 경우의 수를 저장할 배열
int[] dp = new int[target + 1];
// 0을 만드는 경우의 수는 한 가지
dp[0] = 1;

 

1부터 target까지 순회하며 경우의 수를 채워나간다.
각 인덱스마다 nums 배열의 값들의 탐색 결과값을 모두 더한 값을 저장한다.
예를 들어 target이 4일 경우 nums 배열 [1, 2, 3]의 각 값 x에 대해 다음과 같이 정의할 수 있다.

  • x = 1, 3을 더하면 target 값인 4가 되므로 3을 만들 수 있는 경우의 수와 같다 = dp[3]
  • x = 2, 2을 더하면 target 값인 4가 되므로 2을 만들 수 있는 경우의 수와 같다 = dp[2]
  • x = 3, 1을 더하면 target 값인 4가 되므로 1을 만들 수 있는 경우의 수와 같다 = dp[1]

즉, dp[4] = dp[3] + dp[2] + dp[1] 

// target까지의 경우의 수를 채워나감
for(int i = 1; i <= target; i++) {
    // nums 배열의 각 값에 대해서 탐색
    // nums 배열의 각 값을 x라고 할 때 target을 만드는 경우의 수는
    // target - x를 만드는 경우의 수와 같음
    for(int j = 0; j < nums.length; j++) {
        // x가 만들고자 하는 target보다 작거나 같은 경우에만 탐색
        if(nums[j] <= i) {
            // nums배열의 각 탐색값을 더함
            dp[i] += dp[i - nums[j]];
        }
    }
}

 

최종적으로 target의 탐색 결과값을 반환한다.

// target에 해당하는 경우의 수를 반환
return dp[target];

최종 코드

class Solution {
    public int combinationSum4(int[] nums, int target) {
        // 각 인덱스 n에 대하여 n을 만들 수 있는 경우의 수를 저장할 배열
        int[] dp = new int[target + 1];
        // 0을 만드는 경우의 수는 한 가지
        dp[0] = 1;
        
        // target까지의 경우의 수를 채워나감
        for(int i = 1; i <= target; i++) {
            // nums 배열의 각 값에 대해서 탐색
            // nums 배열의 각 값을 x라고 할 때 target을 만드는 경우의 수는
            // target - x를 만드는 경우의 수와 같음
            for(int j = 0; j < nums.length; j++) {
                // x가 만들고자 하는 target보다 작거나 같은 경우에만 탐색
                if(nums[j] <= i) {
                    // nums배열의 각 탐색값을 더함
                    dp[i] += dp[i - nums[j]];
                }
            }
        }

        // target에 해당하는 경우의 수를 반환
        return dp[target];
    }
}