• 【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。

  • 相关阅读:
    使用 supervisor 管理进程
    用gunicorn+gevent启动Flask项目
    pip与apt-get
    Python计算地图上两点经纬度间的距离
    java基础学习总结——数组
    java基础学习总结——异常处理
    java基础学习总结——面向对象1
    java基础学习总结——基础语法2
    java基础学习总结——基础语法1
    java基础学习总结——java环境变量配置
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4439240.html
Copyright © 2020-2023  润新知