标签:
解题思路:
该题对时间有要求,我们使用之前用过的回溯法将会超时。因为回溯法遍历所有种可能,类似于穷举,时间效率肯定不高。
换个思路,我们采用动态规划的思想来看看。
动态规划状态方程:
dp[target]=sum(dp[target-nums[i]]) (for i=0..num.size()-1)
dp[target] 代表一共有多少种可能。
那么从target-nums[i] 变为 target,只有一种途径,也就是加上nums[i];那么这种途径带来的次数是dp[target-nums[i]];
我们遍历所有的nums[i],然后求和即可以得到dp[target]的结果。
解法一:自底向上
class Solution { public: int combinationSum4(vector<int>& nums, int target) { if(target==0) return 1; vector<int> mark(target+1,0); mark[0]=1; for(int i=1;i<=target;i++) { for(int j=0;j<nums.size();j++) { if(i>=nums[j]) { mark[i]+=mark[i-nums[j]]; } } } return mark[target]; } };
class Solution { public: int compute(vector<int>& nums,vector<int>& mark,int target) { if(mark[target]!=-1) return mark[target]; int res = 0; for(int i=0;i<nums.size();i++) { if(target>=nums[i]) res+=compute(nums,mark,target-nums[i]); } mark[target]=res; return res; } int combinationSum4(vector<int>& nums, int target) { if(target==0) return 1; vector<int> mark(target+1,-1); mark[0]=1; int res = compute(nums,mark,target); return res; } };
递归
int combinationSum5(vector<int>& nums, int target) { if (target == 0) return 1; int res = 0; for (int i = 0; i < nums.size(); i++) { if (target >= nums[i]) res += combinationSum4(nums, target - nums[i]); } return res; }
void compute(vector<int>& nums, int target, int sum, int& cnt) { if (sum == target) { cnt++; return; } if (sum > target)return; for (int i = 0; i < nums.size(); i++) { compute(nums, target, sum + nums[i], cnt); } } int combinationSum4(vector<int>& nums, int target) { int cnt = 0; compute(nums, target, 0, cnt); return cnt; }
标签:
原文地址:http://blog.csdn.net/janestar/article/details/52163357