15.三数之和

15.三数之和

一、第一轮思路

三层for循环遍历(真有你的)

二、第二轮思路

以前隐约看到过一个哈希表方法,弄一个map<vector,int>,先储存存两数的数组和两数之和,通过哈希表找到0-x的值,复杂度O(n^2)。

三、看看题解

在这里插入图片描述

我又生产了啥垃圾这是?

主流的做法似乎是排序后使用双指针,不过笔者的两个思路也不算完全八杆子打不着。本题的重点与两数之和不同,注意两数之和题干“你可以假设每种输入只会对应一个答案”,但三数之和题干“返回所有和为 0 且不重复的三元组”,所以笔者两个思路的问题核心都在“去重”这件事上。

对于三层for循环遍历,无法去重,所以该思路不再考虑。

哈希表的方法属于有些可行但没必要,把符合条件的三元组放进vector中,然后再去重,这样是非常费时的,很容易超时,也是这道题目通过率如此之低的根源所在。去重的过程不好处理,有很多小细节,如果在面试中很难想到位。

可以发现,如果固定了前两重循环枚举到的元素 a 和 b,那么只有唯一的 c 满足 a+b+c=0。当第二重循环往后枚举一个元素 b′时,由于 b′>b,那么满足 a+b′+c′=0的 c ′一定有 c′<c,即 c在数组中一定出现在 c 的左侧。也就是说,可以从小到大枚举 b,同时从大到小枚举 c,即第二重循环和第三重循环实际上是并列的关系。有了这样的发现,就可以保持第二重循环不变,而将第三重循环变成一个从数组最右端开始向左移动的指针,即为双指针解法。

四、解题思路

1.双指针部分

对数组先进行排序

定义i j k ,两层循环,外层遍历i,内层移动 j k ,找nums[i]=nums[j]+nums[k],

若nums[j]+nums[k]小了就右移 j ,nums[j]+nums[k]大了就左移 k

2.去重想法

出现符合条件的 j k 后,j++,k–,判断j+1和k-1,与现在相等直接跳过(略有问题,请看4.4.2)

3.代码实战

ac代码如下:

vector<vector<int>> threeSum(vector<int>& nums) {
    sort(nums.begin(), nums.end());
    vector<vector<int>>result;
    int size=nums.size();
    for(int i=0;i<size&&nums[i]<=0;i++){
        if(i!=0)
            if(nums[i]==nums[i-1])
                continue;
        int j=i+1;
        int k=size-1;
        while(j<k){
            long long number1=nums[j]+nums[k];
            if(-nums[i]>number1){
                j++;
            }
            else if(-nums[i]<number1){
                k--;
            }
            else{
                result.push_back({nums[i],nums[j],nums[k]});
                 while(j<k&&nums[j]==nums[j+1]) //if改成while
                    j++;
                while(j<k&&nums[k]==nums[k-1])
                    k--;
                j++;
                k--;
            }

        }
    }
    return result;

}
4.遇到的问题
(1)编译相关

在写for循环条件时,一开始将 i < size && nums[i] <= 0写为了nums[i] <= 0 && < size,在力扣执行会数组越界

(2)去重相关

在对jk去重时,一开始的代码为

  if(j<k&&nums[j]==nums[j+1]) //if改成while
                    j++;
  if(j<k&&nums[k]==nums[k-1])
                    k--;

执行后有一种情况,如果数组两侧都是三个及以上的连续相同数子,如-5,1,1,1,3,4,4,4

j k经历一轮if的去重不够完全,需要修改成while

5.做题感受

复健运动第三题,还遇到了很多零碎细节的小问题,不赘述了,痛苦。
在这里插入图片描述

五、对双指针解法的思考

一般是用于一个有序数组,如果两个指针不会相交即为滑动窗口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值