【CODE】Combination Sum (DFS && dp)

目錄

39. Combination Sum

40. Combination Sum II

216. Combination Sum III

377. Combination Sum IV


39. Combination Sum

Medium

302294Add to ListShare

Given a set of candidate numbers (candidates(without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

The same repeated number may be chosen from candidates unlimited number of times.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [2,3,6,7], target = 7,
A solution set is:[  [7],  [2,2,3]  ]

Example 2:

Input: candidates = [2,3,5], target = 8,
A solution set is:[  [2,2,2,2],  [2,3,3],  [3,5]  ]
#include"pch.h"
#include<iostream>
#include<stack>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
/*39. Combination Sum
1.典型DFS
Runtime: 20 ms, faster than 41.01% of C++ online submissions for Combination Sum.
Memory Usage: 12.7 MB, less than 40.28% of C++ online submissions for Combination Sum.*/
void DFS(vector<int> candidates, int target, int start, vector<int> &out, vector<vector<int> > &res) {
	if (target == 0) {
		res.push_back(out);
		return;
	}
	for (int i = start; i < candidates.size(); i++) {
		if (target - candidates[i] >= 0) {
			out.push_back(candidates[i]);
			DFS(candidates, target - candidates[i], i, out, res);
			out.pop_back();
		}

	}
	return;
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
	vector<vector<int> > res;
	vector<int> out;
	DFS(candidates, target, 0, out, res);
	return res;
}
/*2.給數組排序,遇到大於target的就不再遞歸了
Runtime: 24 ms, faster than 34.62% of C++ online submissions for Combination Sum.
Memory Usage: 12.9 MB, less than 40.28% of C++ online submissions for Combination Sum.*/
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
	sort(candidates.begin(), candidates.end());
	vector<vector<int> > res;
	for (int i = 0; i < candidates.size(); i++) {
		if (candidates[i] > target) break;
		else if(candidates[i]==target){
			res.push_back({ candidates[i] }); break;
		}
		else {
			vector<int> vec = vector<int>(candidates.begin() + i, candidates.end());
			vector<vector<int> > tmp = combinationSum2(vec, target - candidates[i]);
			for (auto a : tmp) {
				a.insert(a.begin(), candidates[i]);
				res.push_back(a);
			}
		}
	}
	return res;
}
/*3.迭代,建立三維數組,dp[i]表示目標數爲i+1的解法的集合,i從1到target,
對於每個i,建立一個二維數組cur,遍歷原數組,如果遍歷到的數字大於i,break;
如果遍歷到的數字=i,那麼當前數字形成一個數組加入cur;
如果遍歷到的數組<i,那麼遍歷dp[i-candidates[j]-1]中的所有數組,
如果當前數字大於數組首元素,則break,否則就將當前數字加入數組開頭,再將數組加入cur
Runtime: 36 ms, faster than 26.08% of C++ online submissions for Combination Sum.
Memory Usage: 18.3 MB, less than 20.83% of C++ online submissions for Combination Sum.*/
vector<vector<int>> combinationSum3(vector<int>& candidates, int target) {
	vector<vector<vector<int> > > dp;
	sort(candidates.begin(), candidates.end());
	for (int i = 1; i <= target; i++) {
		vector<vector<int> > cur;
		for (int j = 0; j < candidates.size(); j++) {
			if (candidates[j] > target) break;
			else if (candidates[j] == i) {
				cur.push_back({ candidates[j] });
				break;
			}
			else {
				for (auto a : dp[i - candidates[j] - 1]) {
					if (candidates[j] > a.front()) continue;
					a.insert(a.begin(), candidates[j]);
					cur.push_back(a);
				}
			}
		}
		dp.push_back(cur);
	}
	return dp[target - 1];
}
int main() {
	vector<int> num = {2,3,6,7};
	vector<vector<int> > res = combinationSum2(num, 7);
	for (int i = 0; i < res.size(); i++) {
		for (int j = 0; j < res[i].size(); j++) {
			cout << res[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

40. Combination Sum II

Medium

133855Add to ListShare

Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

Each number in candidates may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
  [1,2,2],
  [5]
]
#include"pch.h"
#include<iostream>
#include<stack>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
/*40. Combination Sum II
DFS:
Runtime: 8 ms, faster than 85.54% of C++ online submissions for Combination Sum II.
Memory Usage: 11.6 MB, less than 13.16% of C++ online submissions for Combination Sum II.*/
void DFS(vector<int> candidates, vector<int> &out, vector<vector<int> > &res,int target,int start) {
	if (target == 0) {
		res.push_back(out);
		return;
	}
	for (int i = start; i < candidates.size(); i++) {
		if (target - candidates[i] >= 0 ) {
			if (i > start && candidates[i] == candidates[i - 1]) continue;
			out.push_back(candidates[i]);
			DFS(candidates, out, res, target - candidates[i], i+1); 
			out.pop_back();
		}
		else break;
	}
	return;
}
vector<vector<int>> combinationSum1(vector<int>& candidates, int target) {
	vector<int> vis(candidates.size());
	vector<vector<int> > res;
	vector<int> out;
	sort(candidates.begin(), candidates.end());
	DFS(candidates,  out, res, target, 0);
	return res;
}
int main() {
	vector<int> num = { 10,1,2,7,6,1,5 };
	vector<vector<int> > res = combinationSum1(num, 8);
	for (int i = 0; i < res.size(); i++) {
		for (int j = 0; j < res[i].size(); j++) {
			cout << res[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

216. Combination Sum III

Medium

84646Add to ListShare

Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

Note:

  • All numbers will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: k = 3, n = 7
Output: [[1,2,4]]

Example 2:

Input: k = 3, n = 9
Output: [[1,2,6], [1,3,5], [2,3,4]]
#include"pch.h"
#include<iostream>
#include<stack>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
/*216. Combination Sum III
Runtime: 4 ms, faster than 63.71% of C++ online submissions for Combination Sum III.
Memory Usage: 8.6 MB, less than 100.00% of C++ online submissions for Combination Sum III.*/
void DFS(vector<int> &out, vector<vector<int> > &res, int target, int k,int start) {
	if (target == 0 && k == 0) {
		res.push_back(out);
		return;
	}
	else if (target > 0 && k > 0) {
		for (int i = start; i <=9; i++) {
			if (target - i >= 0) {
				out.push_back(i);
				DFS(out, res, target - i, k - 1, i + 1);
				out.pop_back();
			}
			else return;
		}
	}
	return;
}
vector<vector<int>> combinationSum3(int k, int n) {
	vector<vector<int> > res;
	vector<int> out;
	DFS(out, res, n, k, 1);
	return res;
}
int main() {
	vector<vector<int> > res=combinationSum3(3, 9);
	for (int i = 0; i < res.size(); i++) {
		for (int j = 0; j < res[i].size(); j++) {
			cout << res[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

377. Combination Sum IV

Medium

1128135Add to ListShare

Given an integer array with all positive numbers and no duplicates, find the number of possible combinations that add up to a positive integer target.

Example:

nums = [1, 2, 3]
target = 4

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.

Therefore the output is 7.

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?

Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.

#include"pch.h"
#include<iostream>
#include<stack>
#include<string>
#include<vector>
#include<algorithm>
#include<unordered_map>
using namespace std;
/*377. Combination Sum IV
1.DFS:超時*/
void DFS(int &res,int target,vector<int> nums) {
	if (target == 0) {
		res++;
		return;
	}
	for (int i = 0; i < nums.size(); i++) {
		if (target - nums[i] >= 0) {
			DFS( res, target - nums[i], nums);
		}
		else return;
	}
	return;
}
int combinationSum1(vector<int>& nums, int target) {
	sort(nums.begin(), nums.end());
	int res = 0;
	DFS( res, target, nums);
	return res;
}
/*2.與爬樓梯問題相似,假設nums:{x,y,z}
dp[i]=dp[i-x]+dp[i-y]+dp[i-z]
但是[3,33,333],10000,超過long long,無法通過*/
int combinationSum2(vector<int>& nums, int target) {
	sort(nums.begin(), nums.end());
	vector<long long> dp(target+1);
	dp[0] = 1;
	for (int i = 1; i <=target; i++) {
		for (int j = 0; j < nums.size(); j++) {
			if (nums[j] <= i) dp[i] += dp[i - nums[j]];
			else break;
		}
	}
	return dp.back();
}
/*3.遞歸+記憶數組
Runtime: 4 ms, faster than 67.79% of C++ online submissions for Combination Sum IV.
Memory Usage: 10.1 MB, less than 30.00% of C++ online submissions for Combination Sum IV.*/
int digui(vector<int> &nums, int target, unordered_map<int, int> &demo) {
	if (target < 0) return 0;
	if (target == 0) return 1;
	if (demo.count(target)) return demo[target];
	int res = 0;
	for (int i = 0; i < nums.size(); i++) {
		res += digui(nums, target - nums[i], demo);
	}
	demo[target] = res;
	return res;
}
int combinationSum3(vector<int>& nums, int target) {
	unordered_map<int, int> mp;
	return digui(nums, target, mp);
}
int main() {
	vector<int> nums = {3,33,333 };
	cout << combinationSum3(nums,10000);
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章