KSum:
问题1:一组整数中,k个数的和恰好为target的情况由多少种?
问题2:一组整数中,k个数的和恰好为target。输出所有的结果。
TwoSum:
问题3: 一组整数中,找2个数的和恰好为target, 讲满足条件的两个数的下标输出
ThreeSum:
问题4: 一组整数中,找3个数的和恰好为0, 将所有满足条件的三个数输出
#include<iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
using namespace std;
vector<vector<int>> res;
//问题1
void KSum(vector<int> &nums, int k, int target, int index, vector<int> oneRes){
if (k == 0 && target == 0){
res.push_back(oneRes);
return;
}
if (k == 0 || target == 0 || index < 0)
return;
//不考虑当前数
KSum(nums, k, target, index - 1, oneRes);
//考虑当前数
oneRes.push_back(nums[index]);
KSum(nums, k - 1, target - nums[index], index - 1, oneRes);
}
//问题2
int KSum(vector<int> &nums, int K, int target){
vector<vector<vector<int>>> dp(nums.size() + 1, vector<vector<int>>(K + 1, vector<int>(target + 1, 0)));
for (int i = 0; i <= nums.size(); ++i)
for (int k = 0; k <= K; ++k)
for (int t = 0; t <= target; ++t){
if (k == 0 && t == 0)
dp[i][k][t] = 1;
if (!(i == 0 || k == 0 || t == 0)){
//不考虑当前的数
dp[i][k][t] = dp[i - 1][k][t];
//考虑当前的数
if (t - nums[i - 1] >= 0)
dp[i][k][t] += dp[i - 1][k - 1][t - nums[i - 1]];
}
}
return dp[nums.size()][K][target];
}
//Two Sum
//问题3
//数组无序的时候;时间复杂度O(n)
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> index;
for (int i = 0; i<nums.size(); ++i){
if (index.find(target - nums[i]) != index.end())
return{ i, index[target - nums[i]] };
index[nums[i]] = i;
}
return{ 0, 0 };
}
//数组有序的时候;时间复杂度O(n)
vector<int> twoSum_sortedArray(vector<int>& nums, int target) {
for (int i = 0, j = nums.size() - 1; i<j;){
int sum = nums[i] + nums[j];
if (sum == target)
return{ i + 1, j + 1 };//注意数组中的数的标号是从0开始的,还是从1开始的。
if (sum<target)
++i;
else
--j;
}
return{ 0, 0 };
}
//问题4
//Three Sum
//三个数之和为0
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if (nums.empty())return res;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size() - 1; ++i){
int target = -nums[i]; int j = i + 1, k = nums.size() - 1;
while (j < k){
if (nums[j] + nums[k] > target)--k;
else if (nums[j] + nums[k] < target)++j;
else{
res.push_back({ nums[i], nums[j], nums[k] });
while (nums[j] == nums[j + 1] && j < k - 1)++j;
while (nums[k] == nums[k - 1] && k > j + 1)--k;
++j; --k;
}
}
while (nums[i] == nums[i + 1] && i < nums.size() - 1)++i;
}
return res;
}
//三个数之和与target最接近
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int bestDis = INT_MAX;
for (int i = 0; i<nums.size(); ++i){
int j = i + 1, k = nums.size() - 1;
int sum = target - nums[i];
while (j<k){
int dif = sum - nums[j] - nums[k];
if (dif == 0)
return target;
if (abs(dif)<abs(bestDis))
bestDis = dif;
if (dif>0)
++j;
else
--k;
}
}
return target - bestDis;
}
int main(){
vector<int> nums = { 3, 2, 4, 1, 7, 10, 9, 8, 19, 27, 5 };
KSum(nums, 3, 10, 10, vector < int >());
if (res.size() == 0)
cout << "no result" << endl;
else{
cout << "There are " << KSum(nums, 3, 10) << " results!" << endl;
for (auto i : res){
for (auto j : i)
cout << j << " ";
cout << endl;
}
}
vector<int> threesum = { -1, 2, 1, -4 };
cout << threeSumClosest(threesum, 1) << endl;
getchar();
}