一: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;
}