LeetCode-配列-三数の和

4696 ワード

タイトルの説明
n個の整数を含む配列numsを与え,numsにa,b,cの3つの要素が存在するか否かを判断し,a+b+c=0とする.条件を満たし、繰り返さないすべての三元グループを見つけます.
注意:答えに重複する三元グループは含まれてはいけません.練習問題の原文.
問題を解く構想.
3つの数の和を0とすると、nums[i]+nums[j]+nums[k]=0は2つの数の和、すなわちnums[i]+nums[j]=-nums[k]を求めることに変換できる.では、ポインタの移動によって式を満たす数字を検索することができ、ポインタの移動を容易に制御するために、数字のセットが秩序化されていることを前提としています.
では、大体の解題の考え方は以下の通りです.
  • 配列のソート
  • は、3つのポインタi,left,rightを定義する.ポインタiは求和項を指し、ポインタleft,rightはそれぞれ配列の頭部と尾部
  • を指す.
  • -nums[i]=nums[left]+nums[right]のとき式を満たし、ポインタleft,rightは
  • を中部に移動し続ける.
  • -nums[i]>nums[left]+nums[right]のときポインタleftが
  • 中部に移動する.
  • -nums[i]移動する.
  • ポインタleft,rightが交差すると移動を停止し、ポインタiが下に移動し、ポインタleft,rightが
  • リセットする.
    その流れは下図の通りです.
    インプリメンテーション
    public static List> solution(int[] nums) {
        //   
        Arrays.sort(nums);
    
        List> rs = new ArrayList<>();
    
        int i = 0, left = 1, right = nums.length - 1;
    
        while (i < nums.length - 2) {
            while (true) {
                //         
                if (right <= left) {
                    break;
                }
    
                if (-nums[i] == nums[left] + nums[right]) {
                    rs.add(Arrays.asList(nums[i], nums[left], nums[right]));
    
                    //             
                    //            
                    while (true) {
                        if (left >= nums.length - 1) {
                            break;
                        }
    
                        if (nums[left] != nums[left + 1]) {
                            left++;
                            break;
                        } else {
                            left++;
                        }
                    }
    
                    while (true) {
                        if (right <= 0) {
                            break;
                        }
    
                        if (nums[right] != nums[right - 1]) {
                            right--;
                            break;
                        } else {
                            right--;
                        }
                    }
    
                    continue;
                }
    
                if (-nums[i] <= nums[left] + nums[right]) {
                    right--;
                    continue;
                }
    
                if (-nums[i] > nums[left] + nums[right]) {
                    left++;
                    continue;
                }
            }
    
            //           
            while (true) {
                if (i >= nums.length - 1) {
                    break;
                }
    
                if (nums[i] != nums[i + 1]) {
                    i++;
                    break;
                } else {
                    i++;
                }
            }
    
            //i++;
            left = i + 1;
            right = nums.length - 1;
        }
    
        return rs;
    }
    

    原文を参照