4Sum-LeetCode

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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值