1. 程式人生 > >LeetCode 15 3Sum [sort] <c++>

LeetCode 15 3Sum [sort] <c++>

distance () 元組 處理 std targe 三元組 push_back 右移

LeetCode 15 3Sum [sort] <c++>

給出一個一維數組,找出其中所有和為零的三元組(元素集相同的視作同一個三元組)的集合。

C++

先自己寫了一發,雖然過了,但跑了308 ms...
我的做法是先排序,掃一遍,處理出unorder_map<0-a[i],i>的hash表。再\(O(n^2)\)枚舉前兩個元素,查表直接知道第三個元素的位置,然後將三元組加入到答案集合中,通過枚舉時添加的限制條件規避重復元素。
復雜度\(O(n^2)\),由於使用了hash表,常數較大。

class Solution {
public:
    std::vector<std::vector<int>> threeSum(std::vector<int>& nums) {
        std::vector<std::vector<int> > res;
        if(nums.size()<3) return res;
        std::sort(nums.begin(),nums.end());
        const int target = 0;
        std::unordered_map<int,int> ump;
        for(auto i=nums.begin();i!=nums.end();i++)
            ump[target-*i] = std::distance(nums.begin(),i)+1;
        for(auto i=nums.begin();i<nums.end();i++){
            if(i>nums.begin() && *i == *(i-1)) continue;
            for(auto j=i+1;j<nums.end();j++){
                if((j>i+1 && *j== *(j-1))|| ump[*i+*j]-1<=std::distance(nums.begin(),j))continue;
                res.push_back({*i,*j,*(nums.begin()+ump[*i+*j]-1)});
            }
        }
        return res;
    }
};

學習一發沒有常數的\(O(n^2)\),只用了64 ms
排序後,枚舉第一個元素,左右指針夾逼(根據枚舉元素+左指針元素+右指針元素與0的大小關系,判斷移動哪一個指針,移動方向一定是使左右指針所夾範圍更小的)

class Solution {
public:
    std::vector<std::vector<int>> threeSum(std::vector<int>& nums) {
        std::vector<std::vector<int> > res;
        if(nums.size()<3) return res;
        std::sort(nums.begin(),nums.end()); // 先排序
        const int target = 0;
        auto last = nums.end();
        for(auto i = nums.begin();i<last-2;i++){
            auto j = i+1; // 左指針初始化
            if(i>nums.begin()&&*i == *(i-1)) continue; // 避免枚舉重復元素
            auto k = last - 1; // 右指針初始化
            while (j < k){
                if(*i+*j+*k<target){ // 左指針右移,使和變大
                    j++;
                    while (*j==*(j-1)) j++; // 跳過重復元素
                }
                else if(*i+*j+*k>target){ // 右指針左移,使和變小
                    k--;
                    while (*k==*(k+1)) k--; // 跳過重復元素
                }
                else{ // 加入答案集合
                    res.push_back({*i,*j,*k});
                    j++;
                    k--;
                    while (*j==*(j-1) && *k==*(k+1) && j<k) j++; // 跳過重復元素
                }
            }
        }
        return res;
    }
};

LeetCode 15 3Sum [sort] <c++>