LeetCode-Combination Sum IV

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

最开始的想法是使用如下的回溯法,结果超时了,想想的确回溯的规模会特别大(特别是有1存在的时候)需要寻找更高效的解决方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
void getAll(vector<int>& nums, int target, int& result) {
for(int n:nums) {
int t = target-n;
if(t == 0) ++result;
else if(t > 0) getAll(nums, t, result);
else break;
}
}
int combinationSum4(vector<int>& nums, int target) {
int result = 0;
sort(nums.begin(), nums.end());
getAll(nums, target, result);
return result;
}
};

使用DP后发现运行不会超时。

主要思路为使用一个名为records的map记录从1到target的所有历史答案。可以借助历史答案得到当前的答案。

需要注意的是map的value值需要设定为long,否则可能会overflow。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
if(nums.size() == 0) return 0;
sort(nums.begin(), nums.end());
map<int, long> records;
for(int n:nums) records.insert(make_pair(n, 1));
for(int i=nums[0]; i<=target; ++i) {
int t = 0;
if(records.find(i) == records.end()) records.insert(make_pair(i, 0));
for(int n:nums) {
if(i-n < 0) break;
if(records.find(i-n) != records.end()) t += records[i-n];
}
records[i] += t;
}
return records[target];
}
};

使用数组替换map,可以进一步提升运行效率。另外,还可以使用语句if(records[i] > INT_MAX-records[i-n]) break;判断target为某值的时候是否超过INT_MAX,如果超过,就没必要继续计算了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
if(nums.size() == 0) return 0;
vector<int> records(target+1, 0);
records[0] = 1;
for(int i=1; i<=target; ++i) {
for(int n:nums) {
if(i-n < 0) continue;
if(records[i] > INT_MAX-records[i-n]) continue;
records[i] += records[i-n];
}
}
return records[target];
}
};