文章目录
本文地址
Two Sum
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
哈希表:
O(n)的时间和空间复杂度
注意样例:
【0, 4, 3, 0】
0
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int, int> um;// val2index
vector<int> res;
for(int i = 0; i < nums.size(); i++){
int complement = target-nums[i];
unordered_map<int, int>::iterator it = um.find(complement);
if(it != um.end() ){
res.push_back(it->second);
res.push_back(i);
return res;
} else{
um[nums[i]] = i;
}
} return vector<int>(); // not find
}
};
Two Sum II - Input array is sorted
题目链接 Two Sum II - Input array is sorted
Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2.
Note:
Your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution and you may not use the same element twice.
Example:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
下面的代码是O(n)的复杂度,《剑指offer》上也有这道题
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
vector<int> res;
if(numbers.size() == 0) return res;
int i = 0, j = numbers.size()-1;
while(i < j){
if(numbers[i] + numbers[j] == target){
res.push_back(i+1);
res.push_back(j+1);
return res;
}
if(numbers[i] + numbers[j] < target) ++i;
else --j;
} return res;
}
};
Two Sum IV - Input is a BST
Two Sum IV - Input is a BST
Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such that their sum is equal to the given target.
Example 1:
Input:
5
/ \
3 6
/ \ \
2 4 7
Target = 9
Output: True
Example 2:
Input:
5
/ \
3 6
/ \ \
2 4 7
Target = 28
Output: False
推荐题解 链接, 这里讲了3种方法来做这道题
方法一:哈希表记录每个节点的值,时间复杂度O(n), 空间复杂度O(n)。遍历树的方法可以是preorder,inorder 或者 postorder
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool findTarget(TreeNode* root, int k) {
s = unordered_set<int>();
return helper(root, k);
}
bool helper(TreeNode* root, int k){
if(root == NULL) return false;
if(helper(root->left, k)) return true;
if(s.find(k - root->val) != s.end()) return true;
s.insert(root->val);
return helper(root->right, k);
}
private:
unordered_set<int> s;
};
方法2: 利用中序遍历把tree保存在一个数组中,此时得到有序的数组。然后用two sum的方法即可。时间复杂度O(n), 空间复杂度O(n)。
class Solution {
public:
bool findTarget(TreeNode* root, int k) {
v = vector<int>();
helper(root);
int l = 0, r = v.size()-1;
while(l < r){
if(v[l]+v[r] == k) return true;
if(v[l]+v[r] < k) ++l;
else --r;
} return false;
}
void helper(TreeNode* root){
if(root == NULL) return;
helper(root->left);
v.push_back(root->val);
helper(root->right);
}
private:
vector<int> v;
};
方法3:
节点个数为n
, 树高为h
. 那么我们可以对每个节点的值val
搜索 k-val
是否在tree中。
时间复杂度O(nh)
.
class Solution {
public:
bool findTarget(TreeNode* root, int k) {
if(root == NULL) return false;
return dfs(root, root, k);
}
private:
bool dfs(TreeNode* root, TreeNode* cur, int k){
/* root一直为tree的根节点.
当前选择到的节点为cur
2sum目标为k */
if(cur == NULL) return false;
return search(root, cur, k - cur->val)
|| dfs(root, cur->left, k)
|| dfs(root, cur->right, k);
}
bool search(TreeNode* root, TreeNode* cur, int val){
/* 当前选择的节点为cur, 需要搜到的节点值为val. 初试root为tree的根节点 */
if(root == NULL) return false;
return ((root->val == val) && (root != cur))
|| ((root->val < val) && search(root->right, cur, val))
|| ((root->val > val) && search(root->left, cur, val));
}
};
3Sum
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
先选择一个数,然后问题转变为2sum。时间复杂度为 O ( n 2 ) O(n^2) O(n2)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > res;
if(nums.size() == 0) return res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); ++i){
if(i > 0 && nums[i-1] == nums[i]) continue; // nums[i] 不能重复选择
int sum = -nums[i];
int l = i+1, r = nums.size()-1;
while(l < r){
if(nums[l] + nums[r] == sum){
vector<int> v;
v.push_back(nums[i]);
v.push_back(nums[l]);
v.push_back(nums[r]);
res.push_back(v);
while(l+1 < r && nums[l] == nums[l+1]) ++l; // nums[l] 不能重复选择
++l;
while(l < r-1 && nums[r-1] == nums[r]) --r; // nums[r] 不能重复选择
--r;
} else if(nums[l] + nums[r] < sum){
++l;
} else{
--r;
}
}
} return res;
}
};
3Sum Closest
题目链接3Sum Closest
Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
Example:
Given array nums = [-1, 2, 1, -4], and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int res = 0; // assert(nums.size() >= 3)
if(nums.size() == 0) return res;
sort(nums.begin(), nums.end());
unsigned int diff = UINT_MAX;
for(int i = 0; i < nums.size(); ++i){
if(i > 0 && nums[i-1] == nums[i]) continue;
int sum = target - nums[i], l = i+1, r = nums.size()-1;
while(l < r){
int cur = nums[l] + nums[r];
if(cur == sum) return target;
unsigned int ndiff = abs(sum-cur);
if(ndiff < diff){
res = nums[i] + cur;
diff = ndiff;
}
if(cur < sum) ++l;
else --r;
}
} return res;
}
};
4Sum
4sum转化为2sum问题,间复杂度为 O ( n 3 ) O(n^3) O(n3)
class Solution {
public:
vector<vector<int> > fourSum(vector<int>& nums, int target) {
vector<vector<int> > res;
if(nums.size() < 4) return res;
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); ++i){
if(i > 0 && nums[i-1] == nums[i]) continue;
for(int j = i+1; j < nums.size(); ++j){
if(j > i+1 && nums[j-1] == nums[j]) continue;
int sum = target-nums[i]-nums[j];
int l = j+1, r = nums.size()-1;
while(l < r){
if(nums[l] + nums[r] == sum){
vector<int> cur;
cur.push_back(nums[i]);
cur.push_back(nums[j]);
cur.push_back(nums[l]);
cur.push_back(nums[r]);
res.push_back(cur);
while(l+1 < r && nums[l] == nums[l+1]) ++l;
++l;
while(l < r-1 && nums[r-1] == nums[r]) --r;
--r;
} else if(nums[l] + nums[r] < sum) ++l;
else --r;
}
}
} return res;
}
};
4Sum II
4Sum II
Given four lists A, B, C, D of integer values, compute how many tuples (i, j, k, l) there are such that A[i] + B[j] + C[k] + D[l] is zero.
To make problem a bit easier, all A, B, C, D have same length of N where 0 ≤ N ≤ 500. All integers are in the range of -228 to 228 - 1 and the result is guaranteed to be at most 231 - 1.
Example:
Input:
A = [ 1, 2]
B = [-2,-1]
C = [-1, 2]
D = [ 0, 2]
Output:
2
Explanation:
The two tuples are:
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
Time complexity: O(n^2)
Space complexity: O(n^2)
class Solution {
public:
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
m = unordered_map<long long, int>();
int res = 0;
for(auto a: A){
for(auto b: B){
++m[a+b];
}
}
for(auto c: C){
for(auto d: D){
res += m[-c-d];
}
} return res;
}
private:
unordered_map<long long, int> m;
};
k Sum (TBD)
Description1
Given n distinct positive integers, integer k (k <= n) and a number target.
Find k numbers where sum is target. Calculate how many solutions there are?
Example
Given [1,2,3,4], k = 2, target = 5.
There are 2 solutions: [1,4] and [2,3].
Return 2.
class Solution {
public:
/**
* @param A: An integer array
* @param k: A positive integer (k <= length(A))
* @param target: An integer
* @return: An integera
*/
int kSum(vector<int> &A, int k, int target) {
res = 0;
if(k < 1 || A.size() < k) return res;
if(k == 1){
for(int a: A) if(a == target) ++res;
return res;
}
sort(A.begin(), A.end());
helper(A, k, 0, A.size()-1, target);
return res;
}
private:
int res;
void helper(vector<int>& A, int k, int s, int e, int target){
if(k == 2){
while(s < e){
if(A[s] + A[e] == target){
++res;
while(s+1 < e && A[s] == A[s+1]) ++s;
++s;
while(s < e-1 && A[e-1] == A[e]) --e;
--e;
} else if(A[s] + A[e] < target) ++s;
else --e;
}
} else{
/*
int minv = 0, maxv = 0;
for(int j = 0; j < k; ++j){
minv += A[s+j];
maxv += A[e-j];
} if(minv > target || maxv < target) return; */
for(int i = s; i <= e-k+1; ++i){
int minv = 0, maxv = 0; // 可以起到一定的优化作用
for(int j = 0; j < k; ++j){
minv += A[i+j];
maxv += A[e-j];
} if(minv > target || maxv < target) return;
if(i > s && A[i-1] == A[i]) continue;
helper(A, k-1, i+1, e, target-A[i]);
}
}
}
};
样例超时过不了
Input
[1,4,6,9,10,13,14,17,19,22,25,28,30,33,36,37,38,41,42,45,47,49,51,54,57,58,59,62,64,67,69,71,73,74,77]
23
1000
Expected
2485463
此题应该使用dp来做。
参考资料
http://www.cnblogs.com/tenosdoit/p/3649607.html O(n^2)的算法求解4-sum
https://blog.csdn.net/qq_20404903/article/details/80928130 K-sum
https://www.lintcode.com/problem/k-sum/description k-sum的OJ题目