Files
2021-04-24 21:04:28 +08:00

98 lines
3.3 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [377. Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/)
## 题目
Given an array of **distinct** integers `nums` and a target integer `target`, return *the number of possible combinations that add up to* `target`.
The answer is **guaranteed** to 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 的元素组合的个数。题目数据保证答案符合 32 位整数范围。
## 解题思路
- Combination Sum 这是系列问题。拿到题目,笔者先用暴力解法 dfs 尝试了一版,包含的重叠子问题特别多,剪枝条件也没有写好,果然超时。元素只有 [1,2,3] 这三种target = 32这组数据居然有 181997601 这么多种情况。仔细看了题目数据规模 1000基本可以断定此题是动态规划并且时间复杂度是 O(n^2)。
- 本题和完全背包有点像,但是还是有区别。完全背包的取法内部不区分顺序。例如 5 = 1 + 2 + 2。但是本题是 3 种答案 (122)(212)(221)。定义 dp[i] 为总和为 target = i 的组合总数。最终答案存在 dp[target] 中。状态转移方程为:
$$dp[i] =\left\{\begin{matrix}1,i=0\\ \sum dp[i-j],i\neq 0\end{matrix}\right.$$
- 这道题最后有一个进阶问题。如果给定的数组中含有负数,则会导致出现无限长度的排列。例如,假设数组 nums 中含有正整数 a 和负整数 b其中 a>0,b>0,-b<0则有 a×b+(b)×a=0对于任意一个元素之和等于 target 的排列在该排列的后面添加 b a a b 之后得到的新排列的元素之和仍然等于 target而且还可以在新排列的后面继续 b a a b因此只要存在元素之和等于 target 的排列就能构造出无限长度的排列如果允许负数出现则必须限制排列的最大长度不然会出现无限长度的排列
## 代码
```go
package leetcode
func combinationSum4(nums []int, target int) int {
dp := make([]int, target+1)
dp[0] = 1
for i := 1; i <= target; i++ {
for _, num := range nums {
if i-num >= 0 {
dp[i] += dp[i-num]
}
}
}
return dp[target]
}
// 暴力解法超时
func combinationSum41(nums []int, target int) int {
if len(nums) == 0 {
return 0
}
c, res := []int{}, 0
findcombinationSum4(nums, target, 0, c, &res)
return res
}
func findcombinationSum4(nums []int, target, index int, c []int, res *int) {
if target <= 0 {
if target == 0 {
*res++
}
return
}
for i := 0; i < len(nums); i++ {
c = append(c, nums[i])
findcombinationSum4(nums, target-nums[i], i, c, res)
c = c[:len(c)-1]
}
}
```