leetcode 15. 三数之和(sort+双指针)

Posted wz-archer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 15. 三数之和(sort+双指针)相关的知识,希望对你有一定的参考价值。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

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

解:首先考虑这样一个问题,求数组内两数之和为0的数对个数。

  解法1,枚举i,枚举j,时间复杂度为O(n2)//枚举

  解法2,如果数组有序,枚举i,之后j可以通过二分的方法寻找.时间复杂度为O(nlogn)//二分

  解法3,在解法2的基础上,如果枚举i时是单调的,那么j也是单调的,排序后可以通过双指针的方法O(n)求解,当然,因为要排序,所以时间复杂度仍为O(nlogn)

  解法4:遍历i时,如果数字较小,可以声请一个数组用下标映射的方式O(n)求解,数字较大时也可以用各种数据结构,如二叉查找树,平衡树,map等,时间复杂度O(nlogn)

  当问题变成三元组时,枚举第一维i,那么问题就变成了数组内两数之和为-nums【i】的数对个数,上述解法都可以在O(n2logn)的时间复杂度内解决问题,但观察解法3,排序的时间复杂度和查找的时间复杂度是相加的关系,所以在这里解法3的时间复杂度维O(n2+nlogn),总的来说就是O(n2).

  因为求出的三元组也是有序的,所以去重就是和上一个求出的三元组不同就加入结果中。

   注:这个代码还可以进一步优化,代码中对每个左指针j,右指针k都是从n-1开始,但这里明显满足单调性,对于所有的j,只需要一个右指针k即可。

class Solution {
public:
    vector< vector<int> > threeSum(vector<int>& nums) {
        vector< vector<int> >s;
        vector<int>ss;
        sort(nums.begin(),nums.end());
        int n=nums.size();
        ss.push_back(-1);
        ss.push_back(-1);
        ss.push_back(-1);
        for(int i=0;i<n-2;i++){
            if(nums[i]>0)break;
            if(i>0&&nums[i]==nums[i-1])continue;
            int j=i+1,k=n-1;
            for(; j < k ; j++ ){
                
                while( k>j && nums[i] + nums[j] + nums[k] >= 0){
                    if(nums[i]+nums[j]+nums[k]==0&&(ss[0]!=nums[i]||ss[1]!=nums[j]||ss[2]!=nums[k])){
                        ss[0]=nums[i];
                        ss[1]=nums[j];
                        ss[2]=nums[k];
                        s.push_back(ss);
                    }
                    k--;
                }
            }
        }
        //s.push_back(nums);
        return s;
    }
};

 

以上是关于leetcode 15. 三数之和(sort+双指针)的主要内容,如果未能解决你的问题,请参考以下文章

leetcode 15. 三数之和(sort+双指针)

[leetcode] 15. 三数之和

双指针法及题目

双指针法及题目

双指针法及题目

leetcode 每日一题 15. 三数之和