LeetCode 377:组合总和 Ⅳ(Combination Sum IV)—— 题解 ✅

LeetCode 377:组合总和 Ⅳ(Combination Sum IV)------ 题解 ✅

📖 内容概要

给定一个由 不同整数 组成的数组 nums 和一个目标整数 target,

计算并返回 所有可能的组合个数 ,使得这些整数的和为 target。

✅ 元素可重复使用

✅ 顺序不同的序列视为不同组合

✅ 本质是 完全背包 + 排列计数


💡 解题思路

一、问题本质

  • 数字可以无限使用 ✅
  • [1,1,2]、[1,2,1]、[2,1,1] 算 三种方案 ✅

👉 这是一个 排列问题(Permutation)


二、DP 定义

java 复制代码
dp[j] = 凑成金额 j 的排列数

三、状态转移方程

java 复制代码
dp[j] += dp[j - nums[i]]

含义:

  • 使用 nums[i] 作为最后一个数字
  • 新增方案数 = 凑成 j - nums[i] 的方案数

🔥 核心重点:遍历顺序(本题灵魂)

✅ 正确的遍历顺序(排列数)

java 复制代码
for (int j = 0; j <= target; j++) {      // 背包
    for (int i = 0; i < nums.length; i++) { // 物品
        if (j >= nums[i]) {
            dp[j] += dp[j - nums[i]];
        }
    }
}
为什么这样写?
层级 含义
外层 j 枚举总金额
内层 i 枚举所有可用的数字

✅ 每一个金额都可以由任意数字结尾

✅ 自然形成 排列顺序差异

✅ 得到的是 排列数


❌ 错误的遍历顺序(组合数)

java 复制代码
for (int i = 0; i < nums.length; i++) {
    for (int j = nums[i]; j <= target; j++) {
        dp[j] += dp[j - nums[i]];
    }
}

❌ 会限制数字使用顺序

❌ 只能得到组合数


🔑 记忆口诀(非常重要)

完全背包

  • 组合数:先物品,后背包
  • 排列数:先背包,后物品

✅ AC 代码(Java)

java 复制代码
class Solution {
    public int combinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];
        dp[0] = 1; // 凑成 0 有 1 种方式

        // 先遍历背包
        for (int j = 0; j <= target; j++) {
            // 再遍历物品
            for (int i = 0; i < nums.length; i++) {
                if (j >= nums[i]) {
                    dp[j] += dp[j - nums[i]];
                }
            }
        }
        return dp[target];
    }
}

⏱️ 复杂度分析

指标 复杂度
时间复杂度 O(target × nums.length)
空间复杂度 O(target)

🔍 与「零钱兑换 II」的对比

题目 518. 零钱兑换 II 377. 组合总和 IV
是否无限使用 ✅ ✅
是否区分顺序 ❌ 不区分 ✅ 区分
遍历顺序 先物品 先背包
DP 含义 组合数 排列数

✅ 一句话总结

完全背包 + 排列计数 = 外层金额、内层物品,正序遍历。

相关推荐
垆边人似月.3 分钟前
任务混部(200 分档)
算法
言乐69 分钟前
Python区分广度优先深度优先宽度优先的区别
python·算法·深度优先·广度优先·宽度优先
Rnan-prince22 分钟前
LeetCode 股票买卖系列:一个动态规划状态机模板通吃四题
leetcode·动态规划
如意猴26 分钟前
【C++】007 C/C++ 内存管理机制、malloc与new的区别及模板初阶
java·c++·算法
朝朝辞暮i30 分钟前
C++ 第 32 课:main()、rclcpp::init()、spin()、shutdown()
开发语言·c++·算法
圣保罗的大教堂1 小时前
leetcode 3756. 连接非零数字并乘以其数字和 II 中等
leetcode
朝朝辞暮i2 小时前
C++ 第 31C 课:Subscriber 到底是什么
开发语言·c++·算法
Evand J3 小时前
【MATLAB例程】三维RRT+APF路径规划与AOA-TDOA融合定位算法。附代码的下载链接
算法·matlab·路径规划·rrt·tdoa·apf·aoa
海绵宝宝转agent4 小时前
leetCode100算法开源笔记分享
笔记·算法
写后端的胖头鱼4 小时前
时间复杂度 & 空间复杂度
java·数据结构·算法·时间复杂度·空间复杂度