LeetCode 15 3Sum [sort] <c++>
阿新 • • 發佈:2019-01-27
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++>