【LeetCode热题100】【双指针】三数之和

2023-12-05 14:31:41 浏览数 (1)

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] nums[j] nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

示例 1:

代码语言:javascript复制
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0]   nums[1]   nums[2] = (-1)   0   1 = 0 。
nums[1]   nums[2]   nums[4] = 0   1   (-1) = 0 。
nums[0]   nums[3]   nums[4] = (-1)   2   (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

代码语言:javascript复制
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

代码语言:javascript复制
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

提示:

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

题解

前有两数之和用哈希在O(n)的时间复杂度内解决,现有三数之和需要用到双指针在O(n²)内解决

暴力的话需要三层循环而且需要去重复

我们可以先从小到大排序一下元素,那么现在元素是有序的了,而且左边的比右边的小或者相等

如果某元素大于0了,那么这个元素后面是不会有答案出现了,因为后面的元素不会比前面的小

找到一个小于等于0的元素了,让左指针指向后面一个元素,右指针指向最大的元素,把他们相加起来,如果和等于0,那么这三个是一个答案存起来,继续看左边的元素往右有没有相同的元素,如果有的话更新一下左边指针,因为这三个数字的组合已经是答案了,相同的就是重复了,然后同样看右边的元素往左有没有相同的元素,有的话也更新一下

如果和不等于0,和比0小,那么移动左指针让候选元素变大,如果和比0大,那么移动右指针让候选元素变小

排序nlogn,遍历元素n,两层while循环因为循环条件都是一起的加起来也是n,所以就是n²

代码语言:javascript复制
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        if(nums.size()<3)
            return {};
        sort(nums.begin(),nums.end());
        if(nums[0]>0) // 如果最小的都大于0了那么肯定没有
            return {};
        vector<vector<int>>answer;
        for(int i=0;i<nums.size();i  ){
            if(i>0&&nums[i]==nums[i-1])  // 元素相同的不做判断
                continue;
            int left=i 1,right=nums.size()-1;  // 取左右双指针
            while(left<right){
                int sum=nums[i] nums[left] nums[right];
                if(sum==0){
                    answer.push_back({nums[i],nums[left],nums[right]});
                    while(left<right&&nums[left]==nums[left 1]){left  ;}  // 左边相同的去掉
                    while(left<right&&nums[right-1]==nums[right]){right--;}  // 右边相同的去掉
                    left  ;
                    right--;
                }else if(sum<0){  // 和不为0但是小于0说明和太小了移动左指针变大
                    left  ;
                } else{  // 移动右指针变小
                    right--;
                }
            }
        }
        return answer;
    }
};

0 人点赞