15. 三数之和

232 阅读2分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。

题目分析

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

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

 

示例 1:

输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]

思路分析

三数之和为0,如果不存在都是0的情况,当然了也说过不可以包含重复的三元组。那就一定是一个正数,两个负数。或者两个正数一个负数,或者一个正数一个负数一个0

那么第一时间想到的是根据正负数分为两个数组,遍历之前说到的那些可能。

然而这样并没有显著降低时间复杂度。为了降低时间复杂度,我们可以考虑对数组进行排序,排序后先选择一个元素,再根据双指针选择另两个元素。

由于这道题特别强调了重复的问题,所以需要考虑一个复杂情况

[0,0,0,0]

首先是第一个元素遍历时,必须遍历不重复的元素(因为是排序过的数组所以很好判断)

if(i > 0 && nums[i] == nums[i - 1]){
                continue;
}

同样方式限制双指针的第一个就可以了。

具体实现

vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> ret;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        for(int i = 0; i < n - 2; i++){
            if(i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            if(nums[i] > 0 ) return ret;
            int sum = nums[i];
            int k = n - 1;
            for (int j = i + 1; j < n - 1; j ++){
                if (j > i+1 && nums[j] == nums[j - 1])continue;

                while(j < k && nums[j] + nums[k] + sum > 0){
                    k--;
                }

                if(j == k)break;
                if( nums[j] + nums[k] + sum == 0){
                    ret.push_back({nums[i], nums[j], nums[k]});
                }
            }
        }
        return ret;
    }

总结

由于双指针实际上相当于访问了一次数组,因此相当于n^2+ nlogn的复杂度,也就是n^2