前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >57. 三数之和双指针加set暴力去重

57. 三数之和双指针加set暴力去重

作者头像
和蔼的zhxing
发布2018-09-04 11:28:12
9990
发布2018-09-04 11:28:12
举报

给出一个有n个整数的数组S,在S中找到三个整数a, b, c,找到所有使得a + b + c = 0的三元组。

注意事项

在三元组(a, b, c),要求a <= b <= c。

结果不能包含重复的三元组。

样例

S = {-1 0 1 2 -1 -4}, 你需要返回的三元组集合的是: (-1, 0, 1),(-1, -1, 2)

双指针加set暴力去重

三数之和相比于两数之和要稍微复杂一些,如果不加任何思考直接遍历所有可能的组合,这当然是一种方法,但是时间复杂度可能就会变得不能接受,所以一种比较好的方法是排序之后采用双指针的方法。具体算法如下:

  1. 排序。排序可以让数据变得有序,在许多算法中都有使用。
  2. 定义三个指针i,left,right.
  3. i用来遍历数据,从下下标为0一直到sz-3。
  4. 对于每一个i,令left=i+1,right=sz-1,然后检查三个指针所指数据的和, 如果为0,说明找到一个符合条件的组合,把三个数放入vector中然后再放入set中,接着把left++,right--。 如果>0,则说明当前的right偏大,则把right--,因为是排序的,所以整体和会变小。 如果<0,说明当前的left偏小,则把left++,因为是排序的,所以整体的和会变大。(这里变大变小不是一定的,因为可能存在重复的数据,不影响) 这里主要要理解的是如果为0的话为什么left和right同时可以变化,这是因为要求去重,如果只改变一个还符合条件的话一定是重复的,即使两个都改变还是可能会出现重复的组合,所以放在set中进行暴力去重。还有一种写法不用set去重,增加了去重的判断条件,我认为这种写法增加了算法的复杂度,所以没有用。有兴趣可以看这里.

这样对于每个i来说,只遍历其后的数据,而且利用双指针有效避免了一些重复搜索。代码写起来也比较简洁:

代码语言:javascript
复制
 vector<vector<int>> threeSum(vector<int> &numbers) {
        set<vector<int>> sres;
        vector<vector<int>> res;
        int sz=numbers.size();
        if(sz<3)  return res;
        sort(numbers.begin(),numbers.end());      //先排序
        vector<int> tmp;
        
        for(int i=0;i<=sz-3;i++)
        {
            int left=i+1;
            int right=sz-1;
            while(left<right)
            {
                
                if(numbers[i]+numbers[left]+numbers[right]==0)   //符合条件
                {
                    tmp.push_back(numbers[i]);
                    tmp.push_back(numbers[left]);
                    tmp.push_back(numbers[right]);           //放入vector
                    sres.insert(tmp);                     //插入set,去重
                    tmp.clear();                //清空tmp
                    left++;
                    right--;                 //这两个指针都移动,因为原题是要求去重的,如果只移动一个还满足的话肯定是重复的。
                }
                else if(numbers[i]+numbers[left]+numbers[right]<0)
                {
                    left++;             //如果小,就把左边的指针右移
                }
                else 
                right--;               //大的话,就把右边的指针左移
            }
            
        }
        for(auto s:sres)              //去重之后的结果放入vector
        {
            res.push_back(s);
        }
        
        return res;
        
        // write your code here
    }

顺便复习一下set,刚才写的时候竟然用了push(),一段时间不写果然是忘记很快。 set的资料见set 列出一些基本的成员函数以供参考,掌握一些常用的就可以了:

set

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.02.28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 双指针加set暴力去重
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档