LeetCode15.3Sum 3つのデジタルサム

15. 3Sum 3及び数

15. 3Sum

アレイ所与numsN個の整数、そこ要素はBCなるように+ B + C = 0?ゼロの合計を与え、アレイ内のすべてのユニークなトリプレットを検索します。nums

注意:

ソリューションセットは、重複三つ子を含めることはできません。

例:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]
ダブルポインタ

質問の2つの難しさがあります。

  1. ブルートフォースを回避する方法
  2. 描かれた最後の3つの数字の値が繰り返されないことを確実にする方法

本明細書のデュアルモードのポインタを使用していました。まず、第一の配列が基準値として最も左の値に配置されている与えられた、2つのポインタが基準値のいずれかの側に配置された後に除去し、配列番号ポインタの左右のポインタよりも大きいことを知ることは容易です値。そして得られた二最後尾結果の位置ポインタを調整するために、基準値を有する2つのポインタ値の大きさを比較します。処理したときのノートにもう一つのポイントは、その重複した値です。選別後、値が等しい必ずしも隣接しています。私たちは、左端の桁番号の重複に右ポインタの右端の桁デジタル複製に左ポインタのことを確認します。

戻る上記の2つの困難に。ブルートフォースの最初の時間複雑度はO(N ^ 3)でなければなりません。二重ポインタを設定し、重いサイクルが省略され、Oに還元することができる(N ^ 2)。値が第1の基準値の一番左の数字を選択し、繰り返さないために、最初の数字は(右端同じ番号にアクセスしてください)繰り返さ保証することはできません。各ポインタ近似法が評価さについて第二に、左ポインタの値が右側よりも小さくなければならず、特定の基準値に対して、左ポインタの値が小から大に増加され、従って、第二の値できない値に等しいです。繰り返します。第3の値は、同じ方法です。

    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        int numsLen = nums.length;
        List<List<Integer>> result = new ArrayList<>();
        for(int i = 0 ; i < numsLen - 2; i++){
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }
            int target = -nums[i];
            int left = i + 1;
            int right = nums.length -1;
            while(left < right){
                if(target < nums[left] + nums[right]){
                    right --;
                } else if(target > nums[left] + nums[right]){
                    left ++;
                } else {
                    result.add(Arrays.asList(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--;
                    }
                }
            }
        }
        
        return result;
    }
}
地図の使用

そして、上記のように二重のポインタを使用する方法。唯一の違いは、子供が、ポインタは、シフト時に同じ番号遭遇したときに操作する必要は省略することができるので、そのマップが削除重複した値を使用する、ということです。そのため地図の利用、効率がはるかに低くなるが、それでも基本的にダブルポインタの道を使用します。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
		Arrays.sort(nums);
		List<List<Integer>> r=new ArrayList<>();
		HashMap<Integer,Integer> index=new HashMap<>();
		for(int i=0;i<nums.length;i++)
			index.put(nums[i], i);
		for(int i=0;i<nums.length-2;i++){
			for(int j=i+1;j<nums.length-1;j++){
				int target=0-nums[i]-nums[j];
				if(index.containsKey(target) && index.get(target)>j){
					r.add(Arrays.asList(nums[i], nums[j], target));
					j=index.get(nums[j]);
				}
				i=index.get(nums[i]);
			}
		}
		return r;
    }
}
公開された36元の記事 ウォンの賞賛8 ビュー30000 +

おすすめ

転載: blog.csdn.net/qq_32763643/article/details/104221038