⭐LeetCode 15. 3Sum

题目描述

在这里插入图片描述

知识点

排序+双指针

结果

在这里插入图片描述

实现

码前思考

这道题我没有做出来。。。

  1. 暴力思考:求a+b+c = 0,最直观的方法就是枚举a,b,c,也就是组合数 C n 3 C_n^3 ,这样的会使时间复杂度达到 O ( n 3 ) O(n^3) ,显然不可取;
  2. 既然不能暴力,那么我们需要将原问题再次进行剖析,要另辟蹊径(转换问题,等价问题是解决暴力的首选思想),所谓a+b+c = 0,其实就是a = -b-c。也就是对a,我们要去寻找-b-c即可。
  3. 但是,如果我们直接去找,那么这样的时间复杂度仍然是 O ( n 3 ) O(n^3) (枚举a O ( n ) O(n) 乘上枚举-b-c O ( n 2 ) O(n^2) ),但是如果我们对原数组nums进行排序,然后使用 双指针 ,那么枚举-b-c的时间复杂度就变成了 O ( n ) O(n) ,这样总体时间复杂度就为 O ( n 2 ) O(n^2) 了;
  4. 关于不能有重复解的问题,利用上面的排序,我们就可以解决了,真是一举两得。否则,不用排序也挺难解决的,我没写出来就是卡在没有想到排序。
  5. 另外一个小技巧就是,当我们排序完之后,如果遍历到nums[k]大于0时,我们就可以返回结果了,因为后面的数都不可能满足条件了。

代码实现

//采用O(n^2)+hash的解法
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;

        //特判一些特殊的情况:数组长度小于3的情况
        int size = nums.size();
        if(size < 3){
            return res;
        }

        //通过排序来解决重复解的问题
        sort(nums.begin(),nums.end());

        //使用双指针来解决问题
        for(int k=0;k<size;k++){
            //用于已经排序,所以当当前数字nums[k]为整数时,肯定可以停止了
            if(nums[k] > 0){
                break;
            }

            //去除重复解,当nums[k]==nums[k-1]时,说明可以跳过这个k
            if(k>0&&nums[k]==nums[k-1]){
                continue;
            }

            //开始双指针操作
            int target = 0 - nums[k];
            int i= k+1;
            int j= size-1;
            //只要两个指针没有相遇,代表还在进行筛选
            while(i<j){
                if(nums[i]+nums[j] == target){
                    vector<int> tmp;
                    res.push_back({nums[k],nums[i],nums[j]});
                    //排除重复解的情况,即nums[i+1]==nums[i],nums[j-1]==nums[j]
                    while(i<j && nums[i+1] == nums[i]){
                        i++;
                    }
                    while(i<j && nums[j-1] == nums[j]){
                        j--;
                    }
                    i++;
                    j--;
                }else if(nums[i]+nums[j] <target){//意味着i要右移
                    i++;
                }else{  //意味着j要左移
                    j--;
                }
            }

        }

        return res;
    }
};

码后反思

  1. 之前做的时候是遍历a+b,然后利用hash找-c的,结果卡在重复解上,现在想想,只要排个序就能解决这个问题了,以后尝试一下,时间复杂度也是 O ( n 2 ) O(n^2) 这个想法就没有用到双指针了!
  2. 其实,我不知道双指针是什么,我去学学,查漏补缺呀!
  3. ⭐⭐⭐⭐⭐如果找某一个特定元素,一个指针就够了。如果是找两个元素满足一定关系(比如求和等于特定值),需要双指针, 当然前提是数组有序。

参考思路

LeetCode 第 15 号问题:三数之和

发布了173 篇原创文章 · 获赞 3 · 访问量 5219

猜你喜欢

转载自blog.csdn.net/yc_cy1999/article/details/105660092
今日推荐