【力ボタンLeetCode】15三数の和
47603 ワード
タイトル説明(難易度中)
n個の整数を含む配列numsを与え,numsにa,b,cの3つの要素が存在するか否かを判断し,a+b+c=0とする.条件を満たし、繰り返さないすべての三元グループを見つけます.
注意:答えに重複する三元グループは含まれてはいけません.
例えば、所与の配列nums=[−1,0,1,2,−1,−4],
要求を満たす三元群の集合は,[[−1,0,1],[−1,−1,2]]である.
リンク
https://leetcode-cn.com/problems/3sum/
構想
1、暴力列挙、タイムアウト2、ソート後、二重ポインタで衝突し、重さを落とす3、元の配列を前処理し、0は3つ保留し、その他は最大2つ保留4、mapでカウントした3つに分けて異なり、2つ同じ、3つの0、3つの状況討論がある
コード#コード#
ソート後のダブルポインタ:(setコレクションで重み付け)
並べ替え後の二重ポインタ:(ルールで重さを除く)中間点選択ソート後の配列について、0未満の数を選択し、右端のものを選択します.0より大きい数が必要です.ソート後の配列について、0より大きい数を選択します.左端のものを選択します.0より小さい数が必要です.ソート後の配列について、0に等しい場合、2つの0を超える場合、中間の0を選択します.その他の場合、任意に選択します.1つの0はこのようにして重複しないことを保証することができます
状況別特殊処理:(実践証明が遅い)
n個の整数を含む配列numsを与え,numsにa,b,cの3つの要素が存在するか否かを判断し,a+b+c=0とする.条件を満たし、繰り返さないすべての三元グループを見つけます.
注意:答えに重複する三元グループは含まれてはいけません.
例えば、所与の配列nums=[−1,0,1,2,−1,−4],
要求を満たす三元群の集合は,[[−1,0,1],[−1,−1,2]]である.
リンク
https://leetcode-cn.com/problems/3sum/
構想
1、暴力列挙、タイムアウト2、ソート後、二重ポインタで衝突し、重さを落とす3、元の配列を前処理し、0は3つ保留し、その他は最大2つ保留4、mapでカウントした3つに分けて異なり、2つ同じ、3つの0、3つの状況討論がある
コード#コード#
ソート後のダブルポインタ:(setコレクションで重み付け)
class Solution {
public:
vector<vector<int> > threeSum(vector<int>& nums) {
set<vector<int> > ansTemp;
vector<vector<int> > ans;
if(nums.size() < 3){
return ans;
}
sort(nums.begin(), nums.end());
vector<int> tnums;
//
int lnum1, lnum2, lnum3;
tnums.push_back(nums[0]);
tnums.push_back(nums[1]);
tnums.push_back(nums[2]);
lnum1 = nums[0];
lnum2 = nums[1];
lnum3 = nums[2];
for(int i = 3; i < nums.size(); i++){
if(nums[i] != lnum1 || nums[i] != lnum2 || nums[i] != lnum3){
tnums.push_back(nums[i]);
lnum1 = lnum2;
lnum2 = lnum3;
lnum3 = nums[i];
}
}
for(int i = 1; i < tnums.size()-1; i++){
//
if(tnums[i] < 0 && tnums[i] == tnums[i+1]){
continue;
}
if(tnums[i] > 0 && tnums[i] == tnums[i-1]){
continue;
}
int l = 0;
int r = tnums.size() - 1;
while(l < i && i < r){
if(tnums[l] + tnums[r] + tnums[i] == 0){
vector<int> t;
t.push_back(tnums[l]);
t.push_back(tnums[i]);
t.push_back(tnums[r]);
ansTemp.insert(t);
l++;
r--;
}
else if(tnums[l] + tnums[r] + tnums[i] > 0){
r--;
}
else{
l++;
}
}
}
ans.assign(ansTemp.begin(), ansTemp.end());
return ans;
}
};
並べ替え後の二重ポインタ:(ルールで重さを除く)中間点選択ソート後の配列について、0未満の数を選択し、右端のものを選択します.0より大きい数が必要です.ソート後の配列について、0より大きい数を選択します.左端のものを選択します.0より小さい数が必要です.ソート後の配列について、0に等しい場合、2つの0を超える場合、中間の0を選択します.その他の場合、任意に選択します.1つの0はこのようにして重複しないことを保証することができます
class Solution {
public:
vector<vector<int> > threeSum(vector<int>& nums) {
set<vector<int> > ansTemp;
vector<vector<int> > ans;
if(nums.size() < 3){
return ans;
}
sort(nums.begin(), nums.end());
vector<int> tnums;
int lnum1, lnum2, lnum3;
tnums.push_back(nums[0]);
tnums.push_back(nums[1]);
tnums.push_back(nums[2]);
lnum1 = nums[0];
lnum2 = nums[1];
lnum3 = nums[2];
for(int i = 3; i < nums.size(); i++){
if(nums[i] != lnum1 || nums[i] != lnum2 || nums[i] != lnum3){
tnums.push_back(nums[i]);
lnum1 = lnum2;
lnum2 = lnum3;
lnum3 = nums[i];
}
}
for(int i = 1; i < tnums.size()-1; i++){
if(tnums[i] == 0 && tnums[i-1] == 0 && tnums[i+1] == 0){
vector<int> t;
t.push_back(0);
t.push_back(0);
t.push_back(0);
ans.push_back(t);
continue;
}
if(tnums[i] <= 0 && tnums[i] == tnums[i+1]){
continue;
}
if(tnums[i] > 0 && tnums[i] == tnums[i-1]){
continue;
}
int l = 0;
int r = tnums.size() - 1;
while(l < i && i < r){
if(tnums[l] + tnums[r] + tnums[i] == 0){
vector<int> t;
t.push_back(tnums[l]);
t.push_back(tnums[i]);
t.push_back(tnums[r]);
ans.push_back(t);
l++;
while(l < i && tnums[l] == tnums[l-1]){
l++;
}
r--;
while(r > i && tnums[r] == tnums[r+1]){
r--;
}
}
else if(tnums[l] + tnums[r] + tnums[i] > 0){
r--;
while(r > i && tnums[r] == tnums[r+1]){
r--;
}
}
else{
l++;
while(l < i && tnums[l] == tnums[l-1]){
l++;
}
}
}
}
return ans;
}
};
状況別特殊処理:(実践証明が遅い)
class Solution {
public:
vector<vector<int> > threeSum(vector<int>& nums) {
vector<vector<int> > ans;
map<int, int> tm;
for(int i = 0; i < nums.size(); i++){
if(tm.count(nums[i]) == 0){
tm[nums[i]] = 1;
}
else{
tm[nums[i]] += 1;
}
}
// , 0
if(tm.count(0) != 0 && tm.find(0)->second >= 3){
vector<int> t;
t.push_back(0);
t.push_back(0);
t.push_back(0);
ans.push_back(t);
}
//
map<int, int>::iterator iter;
for(iter = tm.begin(); iter != tm.end(); iter++){
if(iter->second >= 2 && iter->first != 0){
if(tm.count(0-iter->first*2) > 0){
vector<int> t;
t.push_back(iter->first);
t.push_back(iter->first);
t.push_back(0-iter->first*2);
ans.push_back(t);
}
}
}
//
vector<int> tnums;
map<int, int> tn;
for(iter = tm.begin(); iter != tm.end(); iter++){
tnums.push_back(iter->first);
}
for(int i = 0; i < tnums.size(); i++){
tn[tnums[i]] = i;
}
for(int i = 0; i < tnums.size(); i++){
for(int j = i+1; j <tnums.size(); j++){
int temp = 0 - tnums[i] - tnums[j];
if(tm.count(temp) > 0 && tn[temp] > j){
vector<int> t;
t.push_back(tnums[i]);
t.push_back(tnums[j]);
t.push_back(temp);
ans.push_back(t);
}
}
}
return ans;
}
};