【3Sum】cpp

题目

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

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
  • 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)

 

代码

复制代码
class Solution {
public:
    vector<vector<int> > threeSum(vector<int> &num) {
            std::vector<std::vector<int> > ret_vector;
            if (num.size() < 3)
            {
                return ret_vector;
            }
            // sort the vector
            std::sort(num.begin(), num.end());
            // visit all the left side element of the current element
            const int target = 0;
            std::vector<int>::iterator end = num.end();
            for (std::vector<int>::iterator i = num.begin(); i != end-2; ++i){
                // ignore first duplicate i
                if ( i > num.begin() && *i==*(i-1)) continue;
                std::vector<int>::iterator j = i+1;
                std::vector<int>::iterator k = end-1;
                while (j<k){
                    const int tmp = *i+*j+*k;
                    if ( tmp < target ){
                        ++j;
                        while ( *j==*(j-1) && j<k ) ++j;
                    }
                    else if ( tmp > target ){
                        --k;
                        while ( *k==*(k+1) && j<k ) --k;
                    }
                    else{
                        int tmp_triple[3] = {*i,*j,*k};
                        std::vector<int> tmp_vector(tmp_triple,tmp_triple+3);
                        ret_vector.push_back(tmp_vector);
                        ++j;
                        --k;
                        while( *j==*(j-1) && *k==*(k+1) && j<k ) {
                            ++j;
                            --k;
                        }
                    }
                }
            }
            return ret_vector;
    }
};
复制代码

 

Tips:

1. 先对传入的vector排序,然后从前向后遍历。原则是:包含*i元素,且满足条件的triple都加入到返回结果中

2. 这里比较困难的一点是排除重复的triple,大概想一想原则,一些极端的case只能试验出来了

另,在mac上编辑的,不知道为什么用数组初始化vector编译不通过,所以采用了比较麻烦的传参方式

===============================================

第二次过这道题,大体思路记得不太清,重新学习了一下“排序+双指针夹逼”方法

参考的blog:http://www.cnblogs.com/tenosdoit/p/3649607.html

复制代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
            vector<vector<int> > ret;
            if ( nums.size()<3 ) return ret;
            std::sort(nums.begin(), nums.end());
            for ( int i=0; i<nums.size()-2; ++i )
            {
                // skip the duplicates elements
                if ( i>0 && nums[i]==nums[i-1] ) continue;  
                Solution::TwoSum(ret, nums, i+1, 0-nums[i]);
            }
            return ret;
    }
    static void TwoSum(vector<vector<int> >& ret, vector<int>& nums, int begin, int target)
    {
            vector<int> tmp;
            int start = begin;
            int end = nums.size()-1;
            while ( begin<end )
            {
                if ( nums[begin]+nums[end]<target ){
                    begin++;
                }
                else if ( nums[begin]+nums[end]>target ){
                    end--;
                }
                else
                {
                    // add a triple
                    tmp.push_back(nums[start-1]);
                    tmp.push_back(nums[begin]);
                    tmp.push_back(nums[end]);
                    ret.push_back(tmp);
                    tmp.clear();
                    // skip the duplicate elements
                    begin++;
                    while ( begin<end && nums[begin]==nums[begin-1] ) begin++;
                    end--;
                    while ( begin<end && nums[end]==nums[end+1] ) end--;
                }
            }
    }
};
复制代码

tips:

1. 先对数组进行排序

2. 固定一个元素,从其后面元素开始,采用两头夹逼的方式进行遍历。(为什么要两边夹逼?因为元素已经从小到大排序好了,向后移动begin可以增加两个元素的和,向前移动end可以减小两个元素的和;采用这样的方式,相当于进可往最大和靠,退可往最小值收,可以保证不漏)

3. 如果遇到重复的元素要跳过去,因为题中要求不能出现重复的triple。

posted on   承续缘  阅读(212)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示