-8,-2,-1,4,5,5,6,12,16
思路:
1) 先排序
2) 注意排除重复元素。
从后往前 for(int i = nums.size()-1; i > 2; i--) 注意这里至少要剩三个元素。
每一个元素nums[i],找出对应的ThreeSum(nums, i-1, target - nums[i])。 要把当前的元素坐标传入,因为要在此元素之前找三个三个的对。
3) ThreeSum
注意排除重复元素。
从后往前 for(int i = nums.size()-1; i > 1; i--) 注意这里至少要剩两个元素。
每一个元素nums[i],找出对应的TwoSum(nums, i-1, target - nums[i])。 要把当前的元素坐标传入,因为要在此元素之前找两个两个的对。
4) 求TwoSum
用两个指针,对在区间范围内的数找,是否两个相加为target。若是target接着往后找!
注意排除重复元素!
<gs id="61339a29-ab6b-4098-910a-2a1a608efdac" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">while</gs><gs id="55c01370-ebf5-47f6-90b9-36fb4e418a6e" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">(</gs>l < r && <gs id="d462942d-e4d6-4126-9f7b-670abbb95d29" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">nums</gs><gs id="9101631a-5b48-41a9-859b-50ed5e09d02b" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">[</gs>l<gs id="2d393698-9d1e-4c1f-a01f-839ec97ba982" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">]</gs>==nums<gs id="b314f502-c008-4dff-9059-1a716ba5abe4" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">[</gs>l-1]) l++;
while<gs id="5ca59368-cd72-486b-8949-7674f174be68" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">(</gs>l < r && <gs id="f5113591-bce9-4238-8d51-457db2db7d6e" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">nums</gs><gs id="906b594b-b9e9-4c25-bc6a-cd9c33bc0012" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">[</gs>r<gs id="4e7dbadb-0398-436e-9ef4-a5c09a3a140e" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">]</gs>==nums<gs id="35570073-98e1-4378-b0d6-016cf8987d1f" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">[</gs>r+1]) <gs id="98ac0f0d-a4de-4b0c-b013-32d377eebe2e" ginger_software_uiphraseguid="638a474f-7fa4-4cad-855f-332a0b980064" class="GINGER_SOFTWARE_mark">r</gs>--;
外层循环i从后往前扫是因为,每次要把大的元素放在后面。
内层寻缘j从前往后扫是因为,要把最小的pair放在前面。
时间复杂度:
由于最后一次TwoSum用的是夹逼方法O(n), 所以是O(n^3)。
如果用brute force,把所有可能的四个数字都算一遍是O(n^4)。
Code (C++):
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
if(nums.size()== 0 || <strong>nums.size() < 4</strong>) return res;
sort(nums.begin(), nums.end());
for(int i = nums.size()-1; <strong>i > 2</strong>; i--) //at least 0,1,2
{
<strong>if(i < nums.size()-1 && nums[i]==nums[i+1]) continue;</strong>
vector<vector<int> > three = threeSum(nums, <strong>i-1</strong>, target - nums[i]); // search three pairs from i-1
for(int j = 0; j < three.size(); j++)
{
three[j].push_back(nums[i]);//最小的三个,要有次序的,加上最大的元素
res.push_back(three[j]);
}
}
return res;
}
vector<vector<int>> threeSum(vector<int>& nums, int end, int target)
{
vector<vector<int> > res;
for(int i = end; <strong>i > 1</strong>; i--)
{
<strong>if(i < end && nums[i] == nums[i+1]) continue;</strong>
vector<vector<int> > two = twoSum(nums, i-1, target - nums[i]);
for(int j = 0; j< two.size(); j++)
{
two[j].push_back(nums[i]);
res.push_back(two[j]);
}
}
return res;
}
vector<vector<int>> twoSum(vector<int>& nums, int end, int target)
{
int l = 0;
int r = end;
vector<int> tmp;
vector<vector<int> > res;
while(l < r)
{
if(nums[l]+nums[r] == target)
{
tmp.push_back(nums[l]);
tmp.push_back(nums[r]);
res.push_back(tmp);
tmp.clear();
//接着往后,找到才算数。
<strong>l++;
r--;
while(l < r && nums[l]==nums[l-1]) l++;
while(l < r && nums[r]==nums[r+1]) r--;</strong>
}
else if(nums[l]+nums[r] > target) r--;
else l++;
}
return res;
}
};