2023-7-15 1 日 1 つの質問
1. トピック番号
18. 四数之和
2. トピックリンク
3. トピックの説明
n 個の整数の配列 nums とターゲット値 target が与えられます。次のすべての条件を満たし、繰り返されない四倍子 [nums[a], nums[b], nums[c], nums[d]] を見つけて返してください (2 つの 4 倍要素が 1 対 1 に対応する場合、2 つは4 倍は繰り返されるとみなされます):
- 0 <= a、b、c、d < n
- a、b、c、dはそれぞれ異なります
- nums[a] + nums[b] + nums[c] + nums[d] == target回答は任意の順序
で返すことができます。
ヒント:
- 1 <= nums.length <= 200
- -10 9 <= nums[i] <= 10 9
- -10 9 <= ターゲット <= 10 9
4. 問題解決コード
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> res;
int n = nums.size();
if(n < 4){
return res;
}
sort(nums.begin(), nums.end());
for(int i = 0; i < n; ++i){
while(i != 0 && i < n && nums[i] == nums[i-1]){
++i;
}
for(int j = i + 1; j < n; ++j){
while(j != i + 1 && j < n && nums[j] == nums[j - 1]){
++j;
}
int left = j + 1;
int right = n - 1;
while(left < right){
long long temp = (long long)nums[left] + nums[right] + nums[i] + nums[j];
if(temp < target){
++left;
} else if(temp == target){
res.push_back({
nums[i], nums[j], 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{
--right;
}
}
}
}
return res;
}
};
5、問題解決のアイデア
(1) このトピックは3 つの数の和の発展版であり、3 つの数の和とあまり変わりません。3 つの数の和がわからない場合は、この記事を読んでください— 2023-07 -08 LeetCode 毎日 1 つの質問 (3 つの数字の合計)
(2) 同じ考え方ですが、問題は 4 つの数を見つけることであり、繰り返されていないものが目標に等しいです。次に、元の配列を最初に並べ替えます。これは、繰り返しを避けるのに役立ちます。
(3) 4 層ループ + ハッシュ判定法を使用すると、非常に時間計算量が高く、問題を通過できないはずです。したがって、私たちは住むのに適した別の木を選ばなければなりません。最初の数値をトラバースするように最も外側のループを設定します。結果の最初の数値を異なるものにするには、その数値が前の数値と同じである場合、その数値が値になる可能性がすべて判明していることになります。は必要ありません。最初の数値も同じ値 i++ です。
(4) このとき、問題を 3 つの数値の合計の問題に変換しましたが、求めている数値の合計は target と等しくなく、target - nums[i] と等しくなります。3つの数字の合計についてはこの記事で詳しく書いているので、詳しくは説明しません。ただし、大まかな考え方は (3) と同じで、繰り返しを行わない方法で、数値が 2 つしか残っていない場合は、ダブル ポインター法を使用して時間を短縮します。