1.問題の説明:
n個の整数numsの配列を提供し、numsに3つの要素a、b、cがあるかどうかを判別して、a + b + c = 0?条件を満たし、繰り返さないすべてのトリプルを見つけてください。
注:回答に重複したトリプルを含めることはできません。
例:
与えられた配列nums = [-1、0、1、2、-1、-4]、
会うようにトリプルの設定要件:
[
[-1、0、1]、
[-1、-1、2]
]
ソース:
リンク(LeetCode):https: //leetcode-cn.com/problems/3sum
2.思考分析:
①トピックはまだわかりやすいですが、以前は4桁のカラーバックルを作成しました。4つのポインターを使用する方法は、以前の4つのポインターと似ているため、3つのポインターを使用できます。ポインタを使用して実行します。他の方法を使用して実行すると、面倒でタイムアウトが簡単に発生します。たとえば、再帰的なデータが小さい場合は解決できます。首輪の最後の1千から2千のデータのように、それを実行することはできません。タイムアウトしてしまい、重複するデータが多いと再帰的に面倒です。
②まず、配列をソートして、要素を取り出して後で繰り返すかどうかを判断できるようにする必要があります。最初は、最初のポインタが最初の要素の位置を指し、2番目のポインタが2番目の要素を指します。次の要素の位置、3番目のポインタは最後の要素の位置を指しており、これらの位置はループ内で下に移動します。問題には一意の番号が必要であることに注意してください。したがって、要素が同じである場合、どの要素を取り出して追加するかは同じであるため、リサイクル時に最初に重複排除を決定する必要があります。
③現在追加されているa、b、cの要素が0未満の場合、bポインターは1ビット右に移動し、0より大きい場合、cは1ビット左に移動します。移動するときは、bがc未満であることを確認する必要があります。数値の位置は正しいです。加算の結果が0に等しい場合は、要素bおよびcで繰り返される次の要素に移動する必要があります(位置bおよびcから取り出された次の要素が繰り返されないようにするため)。右シフト、c左シフト
④したがって、最初は位置aの要素を重複排除する必要がありますが、最初は位置bを重複排除する必要はありません。追加された要素が0のときにbの位置が重複排除されるため、最初は位置bの重みです。要素が0の場合、繰り返し判断が発生してタイムアウトになります。また、最初にb要素に移動しましたが、送信に関する最後の2つのテストデータがタイムアウトしたことがわかりました。 b位置の重み
3.コードは次のとおりです。
class Solution {
public static List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
int len = nums.length;
for (int a = 0; a <= len - 3; ++a){
//优化
if (nums[a] > 0) return res;
//去重
if (a > 0 && nums[a] == nums[a - 1]) continue;
int b = a + 1, c = len - 1;
while (b < c){
int target = nums[a] + nums[b] + nums[c];
if (target < 0) ++b;
else if (target > 0) --c;
else {
List<Integer> newEle = new ArrayList<>();
newEle.add(nums[a]);
newEle.add(nums[b]);
newEle.add(nums[c]);
res.add(newEle);
//去重
while (b < c && nums[b] == nums[b + 1]) ++b;
//去重
while (b < c && nums[c] == nums[c - 1]) --c;
++b;
--c;
}
}
}
return res;
}
}