2023-07-08 1 日 1 つの質問
1. トピック番号
15. 三数之和
2. トピックリンク
3. トピックの説明
整数配列 nums を指定して、i != j、i != k、および j != k を満たし、さらに nums[ を満たすトリプル [nums[i], nums[j], nums[k]] があるかどうかを判断します。 i] + nums[j] + nums[k] == 0 。お願いします
合計が 0 になり、重複しないすべてのトリプルを返します。
**注意:** 回答に 3 つの繰り返しを含めることはできません。
ヒント:
- 3 <= nums.length <= 3000
- -10 5 <= nums[i] <= 10 5
4. 問題解決コード
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ret;
sort(nums.begin(), nums.end());
int n = nums.size();
if(nums[0] + nums[1] + nums[3] > 0){
return ret;
}
for(int i = 0; i < n; ++i){
if(i != 0 && nums[i] == nums[i-1]){
continue;
}
int left = i + 1;
int right = n - 1;
while(left < right){
int temp = nums[i] + nums[left] + nums[right];
if(temp == 0){
ret.push_back({
nums[i], nums[left], nums[right]});
left++;
right--;
while(left < right && nums[left] == nums[left - 1]){
++left;
}
while(left < right && nums[right] == nums[right + 1]){
--right;
}
} else if(temp < 0){
++left;
} else{
--right;
}
}
}
return ret;
}
};
5、問題解決のアイデア
(1) 今回のお題は、配列から足して0になる3つの数字の組み合わせをすべて見つけるというもので、問題は<1>その数字を見つける方法<2>繰り返さない方法に変形します。
(2) 最も単純な 3 サイクル法を使って乱暴に列挙すると、時間計算量がシステムの判断の範囲を超えて間違っているはずなので、別の方法を探す必要があります。このような問題に遭遇した場合、通常は Sort を使用します。高度な前処理によって。配列を最小値から最大値の順に数値的に並べ替えます。そして、配列には少なくとも 3 つの要素が必要であることはすでにわかっています。次に、最初に最小 3 つの数値の合計が 0 より大きいかどうかを判断します。最小 3 つの数値の合計が 0 より大きい場合、トリプルは存在しないはずです。要件を満たすもの。
(3) ポインタ i を介して配列を走査し、最初の数値を見つけます。i が 0 に等しくなく、nums[i] が nums[i-1] に等しい場合は、判定をスキップします (最初の数値が繰り返されるため)。
(4) 最初の数が決定され、残りの 2 つの数が区間 [i + 1, n - 1] で取得されます。ダブル ポインターが使用され、左側は i+1 を指し、右側は n-1 を指します。temp は nums[i] + nums[left] + nums[right] に等しいことに注意してください。temp が 0 に等しい場合、結果、left++、right– を意味し、その後 nums[left] が nums に等しいかどうかを判断します。 [left - 1] と nums [right] が nums[right + 1] に等しいかどうか、等しい場合、ポインタは移動し続けます。また、left < right である限り、ポインタは移動できます。temp が 0 未満の場合は、数値が小さいことを意味し、左ポインタが右に移動します。temp が 0 より大きい場合は、数値が大きすぎることを意味し、右ポインタが左に移動します。
(5) 最後に、結果の配列を返します。