Leetcode 15. 3Sum

本文探讨了在给定整数数组中寻找三个数使它们的和为零的问题,并提出了一种有效的方法——先排序再使用双指针技巧来解决。通过避免重复计算确保结果的独特性,最终达到O(n²)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note: The solution set must not contain duplicate triplets.

For example, given array S = [-1, 0, 1, 2, -1, -4],

A solution set is:

[
  [-1, 0, 1],
  [-1, -1, 2]
]

思路:
1. 简单粗暴的做法就是三重循环,找到答案。如何降低复杂度?2sum时,用hash降低了复杂度。而且我们也知道,除了hash,还可以用two pointer也可以降低复杂度。用hash不好去重复!
2. 先排序,然后用two pointer,普通的遍历,总是从左往右,two pointer则是一个在左边,一个在右边,根据不同的条件,判断是移动左边还是移动右边或者同时移动,最后左右两个指针在中间相遇,这也是一种遍历方式。这就说明了,简单的遍历不能够挖掘出问题的本质,就要用two pointer.
3. sorting+two pointer, 复杂度o(n^2)。排序配合two pointer,很常用,不然不知道调整那一个pointer。方法是:在每一个位置i处,让这个位置的值等于c,然后在[i+1,n-1]找两个数相加等于0-c,在这个区间用two pointer,根据nums[left]+nums[right]和0-c的关系,决定如何移动指针。
4. 如何取重复?由于给的序列有重复的元素,必须在移动指针的时候判断是否重复。判断重复有三个地方,因为三个元素都需要判断,第一个是在位置i,判断nums[i]==nums[i-1],相等则说明重复;在用two pointer遍历[i+1,n-1],当找到一对相等的数,就要判断left/移动后和移动前是否相等,等则需要继续移动!

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        //sorting+two pointer
        int n=nums.size();
        vector<vector<int>> res;
        vector<int> cur(3,0);
        if(n<3) return res;
        sort(nums.begin(),nums.end());
        for(int i=0;i<n-2;i++){
            if(i>0&&nums[i]==nums[i-1]) continue;//去重复
            int left=i+1,right=n-1;
            int newtarget=0-nums[i];
            while(left<right){
                int curSum=nums[left]+nums[right];
                if(newtarget==curSum){
                    cur={nums[i],nums[left],nums[right]};
                    res.push_back(cur);
                    left++;
                    right--;
                    while(left<right&&nums[left-1]==nums[left])//去重复,一般就是skip
                        left++;
                    while(left<right&&nums[right+1]==nums[right])//去重复,一般就是skip
                        right--;
                }else if(curSum>newtarget)
                    right--;
                else
                    left++;
            } 
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值