力扣377-组合总和IV

动态规划:给你一个由不同整数组成的数组nums,和一个目标整数target。请你从nums中找出并返回总和为target的元素组合的个数。

组合总和IV

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

动态规划(二维数组)

在本题中,顺序不同的序列被视作不同的组合。若没有该要求,则为普通的组合问题,就可以采用完全背包的思路进行求解,此时示例1的所有组合为(1, 1, 1, 1)、(1, 1, 2)、(1, 3)、(2, 2),输出结果应为4。本题实则为排列问题,不能直接使用完全背包的思路进行求解。

第一步:确定DP数组及下标含义

dp[i][j]定义为:在组合长度为i时,其元素之和为j的组合个数

题目指出nums中的各个元素都是正整数,因此在极端情况下target可由target个1相加得到,因此dp数组的行数设定为target+1

输出结果即为dp数组最后一列之和:dp[0][target] (组合长度为1时,其元素之和为target的组合个数) + dp[1][target] (组合长度为1时,其元素之和为target的组合个数) + …… + dp[target][target] (组合长度为target时,其元素之和为target的组合个数)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
        j 
i     0   1   2   3   4
      ---------------------
0     [?   ?   ?   ?   ?]
1     [?   ?   ?   ?   ?]
2     [?   ?   ?   ?   ?] 
3     [?   ?   ?   ?   ?] 
4     [?   ?   ?   ?   ?] 
    				   
        return dp[0][4] + …… + dp[1][4]

第二步:确定递推公式

dp[i][j]为长度为i时的组合,是由长度为i+1的组合在末尾添加一个数字构成,而末尾添加的数字可以是nums数组中的任何一个。当末尾添加的数字选择nums[0]的时候,对于长度为i+1的组合,需要其元素之和为j-nums[0],满足这样的组合个数为dp[i-1][j-nums[0]]。对于末尾选择其他数字,同理可得。因此其转移方程为:

$$ dp[i][j] = \sum_{i=1}^{nuns.length} dp[i-1][j-nums[k]], j-nums[k] \geq0 $$
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
        j 
i     0   1   2   3   4
      ---------------------
0     [1   0   0   0   0]
1     [?   ?   ?   ?   ?]
                  nums = {1,2,3}
    	  dp[1][2] = dp[0][2-1] + dp[0][2-2] = 0 + 1 = 1
2     [?   ?   ?   ?   ?] 
3     [?   ?   ?   ?   ?] 
4     [?   ?   ?   ?   ?] 

第三部:DP数组的初始化

当组合的长度为0时,各元素之和只能为0,因此要想让和为0有且只有这一个方案,即dp[0][0]=1,第一行的其他元素全部为0

1
2
3
4
5
6
7
8
        j 
i     0   1   2   3   4
      ---------------------
0     [1   0   0   0   0]
1     [?   ?   ?   ?   ?]
2     [?   ?   ?   ?   ?] 
3     [?   ?   ?   ?   ?] 
4     [?   ?   ?   ?   ?] 

第四步:确定遍历顺序

转移方程表明当前行取决于上一行,因此外层循环为遍历i、内层循环遍历j

第五步:举例推导

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
        j 
i     0   1   2   3   4
      ---------------------
0     [1   0   0   0   0]
1     [0   1   1   1   0]
2     [0   0   1   2   3]  (1, 3) (2, 2) (3, 1)
3     [0   0   0   1   3]  (1, 1, 2) (1, 2, 1) (2, 1, 1)
4     [0   0   0   0   1]  (1, 1, 1, 1)
                       
                       7

Java代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class combinationSum4 {
    static class Solution {
        public int combinationSum4(int[] nums, int target) {
            // i为组合的长度 组合的最大长度为target
            // j为组合中各元素之和的目标值
            int[][] dp = new int[target + 1][target + 1];
            // 组合长度为0时的元素之和为0
            dp[0][0] = 1;
            // 输出结果为最后一列值之和
            int res = 0;
            for (int i = 1; i <= target; i++) {
                for (int j = 0; j <= target; j++) {
                    for (int k = 0; k < nums.length; k++) {
                        // 状态转移方程
                        if (j - nums[k] >= 0) {
                            dp[i][j] = dp[i][j] + dp[i - 1][j - nums[k]];
                        }
                    }
                }
                // 累加最终的输出结果
                res = res + dp[i][target];
            }
            return res;
        }
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        System.out.println(sol.combinationSum4(new int[]{1, 2, 3}, 4));
    }
}
Licensed under CC BY-NC-SA 4.0
皖ICP备2025083746号-1
公安备案 陕公网安备61019002003315号



使用 Hugo 构建
主题 StackJimmy 设计