leetcode [377] 组合总和

image

错误思路:

一开始是按完全背包问题去解决,即外层循环为数组,内层循环为target,结果不对,因为每一个target可以以数组中任何数字结尾。题目中虽然写着组合,但其实这是一个排列问题,与顺序有关。

错误代码如下:

    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];
        for (int num : nums) {
            for (int t = num; t <= target; t++) {
                dp[t] = dp[t] + dp[target - t];
            }
        }
        return dp[target];
    }

正确解法:

1、记忆搜索法

我们可以使用递归的方式查找到target对应的排序数
f(target) = f(target - num1) + f(target - num2) + .... f(target - numn)

注意f(0) = 1,总和为0时只有一种组合结果。

可以写出如下递归函数:

    int dfs(int target, int[] nums) {
        if (target == 0) {
            return 1;
        }
        int r = 0;
        for (int num : nums) {
            if (target >= num) {
                r += dfs(target - num, nums);
            }
        }
        return r;
    }

该递归函数有很多重复调用的情况,可以使用数组来将每一次的结果进行缓存,改进后代码:

    int dfs(int target, int[] nums, int[] dp) {
        if (target == 0) {
            return 1;
        }
        if (dp[target] != -1) {
            return dp[target];
        }
        int r = 0;
        for (int num : nums) {
            if (target >= num) {
                r += dfs(target - num, nums, dp);
            }
        }
        dp[target] = r;
        return r;
    }

完整代码:

class Solution {

    public static void main(String[] args) {
        System.out.println(new Solution().combinationSum4(new int[]{1, 2, 3}, 4));
    }

    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];
        Arrays.fill(dp, -1);
        return dfs(target, nums, dp);
    }

    int dfs(int target, int[] nums, int[] dp) {
        if (target == 0) {
            return 1;
        }
        if (dp[target] != -1) {
            return dp[target];
        }
        int r = 0;
        for (int num : nums) {
            if (target >= num) {
                r += dfs(target - num, nums, dp);
            }
        }
        dp[target] = r;
        return r;
    }
}

2、递推法

递归法是自顶向下的,递推法是自底向上,动态规划

    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];
        dp[0] = 1;
        for (int i = 1; i <= target; i++) {
            for (int num : nums) {
                if (i >= num) {
                    dp[i] += dp[i - num];
                }
            }
        }
        return dp[target];
    }
posted @ 2024-07-19 17:51  Hekk丶  阅读(38)  评论(0)    收藏  举报