力扣题Threesum

最近开始刷力扣题,想给自己觉得对自己有启发的题目写博客,记录自己的成长。

题目分析

题目是这样的,给定一个数组,求数组中三个数加起来和为0的数,特别注意,不能包含重复的元组。首先分析题目,为了排除重复,我们需要对数组进行排序,因为排完序之后,C++中algorithm中sort()复杂度围为O(nlogn)可以忽略,如果碰到一样的值就可以直接跳过。给一个简单的例子。[-1,0,1,2,-1,-4],排完序之后[-4,-1,-1,0,1,2],比如首指针碰到第一个-1,找到两个元组[-1,-1,2],[-1,0,1], 而后碰到第二个-1就直接跳过不需要进行查找,因为这样就避免了重复。

解决思路 (排序+三指针)

针对排完序的数组,我们设置k为遍历数组指针,i,j为寻找匹配项的指针,一个从前往后,一个从后往前,每次i等于k+1,j等于数组长度-1:

  1. 如果nums[i]+num[j]+num[k]<0,则说明三个数和小了,则移动i,i++;
  2. 如果nums[i]+num[j]+num[k]>0,则说明三个数和大了,则移动j,j++;
  3. 否则,三数和等于=0,为我们需要的元组,记录nums[i],num[j],num[k],然后将i,j指针移到与当前nums[i],num[j]不同的下标。

代码

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());
         if(nums.size()<3)        //数组长度小于3,不存在三数之和等于0;
             return res;
        for(int k=0;k<=nums.size()-3;k++)      //k为遍历数组指针,后面有i,j,所以K只用遍历到nums.size()-3
        {
            if(nums[k]>0)                   //当前最小值都大于0,不存在三个正数之和等于0
                break; 
            if(k>0 && nums[k]==nums[k-1])    continue;    //如果当前值与前面的值相等直接跳过,避免出现重复元组
            
            int i=k+1;
            int j=nums.size()-1;
            while(i<j)
            {
                if(nums[i]+nums[j]+nums[k]>0)
                    j--;
                else if(nums[i]+nums[j]+nums[k]<0)
                    i++;
                else{
             
                     res.push_back(vector<int>{nums[k],nums[i],nums[j]});
                     while(i<j&&nums[i]==nums[i+1])         
                         i++;
                    while(i<j&&nums[j]==nums[j-1])
                        j--;
                    i++;
                    j--;
                }
            }
            
        }
        return res;
    }
};

最后结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值