leetcode 18 四数之和

### 题目

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

示例:

给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

满足要求的四元组集合为:
[
  [-1,  0, 0, 1],
  [-2, -1, 1, 2],
  [-2,  0, 0, 2]
]

### 思路

                和三数之和一样的,首先将数组进行排序,其次选择第一个数固定住,然后后面三个数进行移动,例如此时此刻选择的第一个数的下标是i,那么第二个数下标则是i+1,第三个是i+2,第四个就是nums.size()-1,然后就和三数之和一样了,如果四个数相加结果大于target,那么就将第四个数的下标减一,如果小于target,就将第三个数的下标加一,这样进行遍历,直到最后第三个数的下标大于等于第四个数的下标,此时不算直接结束,将第二个数的下标加一,继续进行一样的遍历,第二个数的下标直到到达nums.size()-3截止,然后将第一个数的下标加一,继续进行上述的遍历循环,所以综上,程序的时间复杂度是N^3。


                而且这个思路可以扩展到k个数的和,同样是先排好序,然后确定第一个数的下标,第二个数的下标,第三个数的下标,.......一直到第k个数为nums.size()-1,然后依然是根据k个数相加的和来进行第k个数和第k-1个数的下标的移动方式,等到第k-1和第k个数的下标相交之后,再将第k-2个数的下标加一,继续进行上面的遍历,第k-2个数的下标加一到达可以到达的最大值之后,再将第k-3个数的下标加一进行同样的循环运算。所以复杂度为N^(k-1),只是过程中同样要注意不得重复。

### code

     

class Solution{
        public: 
        vector<vector<int>> fourSum(vector<int>& nums, int target) {
            //三数之和的进阶版本
            sort(nums.begin(),nums.end());
            vector<vector<int> > res;
            if(nums.size()<4)
                return res;
            int a,b,c,d,l=nums.size();
            for(a=0;a<=l-4;a++){
                if(a==0||nums[a]!=nums[a-1]) {     //防止重复
                for(b=a+1;b<=l-3;b++){
                    if(b==a+1||nums[b]!=nums[b-1]){ //防止重复
                    c=b+1,d=l-1;
                    while(c<d){
                        if(nums[a]+nums[b]+nums[c]+nums[d]<target)
                            c++;
                        else if(nums[a]+nums[b]+nums[c]+nums[d]>target)
                            d--;
                        else{
                            res.push_back({nums[a],nums[b],nums[c],nums[d]});
                            c++;
                            d--;
                            while(c<d&&nums[c-1]==nums[c])      //防止重复
                                c++;
                            while(c<d&&nums[d+1]==nums[d])      //防止重复
                                d--;
                            
                        }
                    }
                    }
                }
                }
            }
            return res;
        }
    };

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值