一: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, and you may not use the same element twice.
Example:
Given nums = [2, 7, 15, 11], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
思路:如果之前做过 Contiguous Array 题目,那么这个题目很容易。遍历数组,使用 ordered_map 数据结构(在 Contiguous Array 中已经说明过为什么使用 ordered_map 比 map更快了),保存每个元素期望配对的值 ( target - nums[i] ),以及对应的下标 i .判断当前的值,是否保存在 ordered_map 数据结构中,如果存在,则返回解。
//该方法总的时间复杂度是 O(n),目前在LeetCode中击败了 %99.98 码友
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> mp;
for(int i = 0;i<nums.size(); ++i)
{
if(mp.find(nums[i])!=mp.end()){ //在数据不超过千万级别的情况下,.find 时间复杂度是 O(1)
int idx = mp[nums[i]];
return {idx,i};
}else{ //保存 target - num[i] 的值到map
int value = target - nums[i];
mp[value] = i;
}
}
return {};
}
拓展,如果不是结果返回下标,而是直接返回数组的值,还有什么解法? 可以首先给数组sort排序,耗时 O(nlogn);然后通过最前下标b,末尾下标e;如果nums[b] + nums[e] > target ,那么 --e;如果 nums[b] + nums[e] < target , 那么 ++b;相等则返回值。在 3 sum的问题上,由于需要处理重复的值,所以不宜再采用ordered_map方法。采用先排序后处理的方式更加简便。
二:THREE SUM,
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问题,是3sum问题的一个子问题。对于nums[i],转嫁为求在 [ i+1,nums.size() ) 区间的 2sum = (target - nums[i]) 的2sum问题。同理,3sum也是4sum的一个子问题。该方法时间复杂度O(n^2)
vector<vector<int>> threeSum(vector<int>& nums){
int target = 0;
vector<vector<int>> rlt;
sort(nums.begin(),nums.end());
for(int i=0;i<(int)nums.size() - 2;++i) //注意啦,size_t(0) - 2 会提升为无符号数!
{
//特别注意需要去除重复,注意不要搞成了 if (nums[i] == nums[i+1]),nums[i]都没有机会在求解区域就被过滤掉了!
if(i>0 && nums[i] == nums[i-1])
continue;
if(nums[i] + nums[i+1] + nums[i+2] > target)
return rlt;
//问题缩小为,求nums在 [i+1, nums.size()) 区间的 2sum问题
int ts = target - nums[i];
int b = i+1;
int e = nums.size() - 1;
while(b<e)
{
if(nums[b]+nums[e] > ts)
--e;
else if(nums[b]+nums[e] < ts)
++b;
else{
rlt.push_back(vector<int>{nums[i],nums[b],nums[e]});
//注意可能有多个重复的值,需要去除
while((b < e) && (nums[b +1] == nums[b])) ++b;
while((b < e) && (nums[e -1] == nums[e])) --e;
++b; --e;
}
}
}
return rlt;
}