[LeetCode-中問] 18. 4つの数字の和

トピック

ここに画像の説明を挿入します

方法 1: ダブルポインタ (固定 2 移動 2)

この質問は、[LeetCode-Medium Question] 15 を参照できます。 3 つの数値
の合計の違いは、 3 つの数値の合計は、for ループを使用して数値を固定し、前後の 2 つのポインターをスライドに設定するだけであることです。合計値とターゲット値の比較に基づきます。

この質問も同じです。やるべきことは 2 つの数値を修正することです。2 つの for ループを使用して 2 つの数値を修正し、前後の 2 つのポインタを設定して、合計の比較に基づいてポインタをスライドさせる必要があります。値と目標値。

注意すべき処理内容が多く、条件を満たせない場合には事前に処理して時間を短縮する必要があります。
ここに画像の説明を挿入します

class Solution {
    
    
//for定2 指针动2
    public List<List<Integer>> fourSum(int[] nums, int target) {
    
    
      int len =  nums.length;
      if(nums == null||len < 4 ) return new ArrayList<>();
      List<List<Integer>> res = new ArrayList<>();
      List<Integer> zres = null;
      Arrays.sort(nums);
      for(int i = 0 ;i< len-3 ;i++){
    
    
           //本身就是排序的数组  若第一个数就大于等于target了那么再加上任何一个数都会大于target,所以直接break
        //    if(nums[i]>target)  break;
        //这个条件不能要(对比LeetCode 15. 三数之和)  如果target是负数,第一个数大于target  在往下加可能会越来越小也是可以=taget的
                                     //但是如果target为0或正数,那么第一个数大于target  往下加会越来越大
          //去重操作  如果nums[i]==nums[i-1] 会得到一份与nums[i-1]一样的结果集
          if(i>0&&nums[i]==nums[i-1]) continue;
           // 若以i开头的四个元素就已经大于target了 那就无需做任何操作了,没必要了,在往后面加再怎么也会大于target
          if((long)nums[i]+nums[i+1]+nums[i+2]+nums[i+3] > target) break;
          // 若以i开头元素和数组末尾的三个元素就还小于target了 那就没必要做此次循环,毕竟i加上后面最大的三个数都比target小
          if((long)nums[i]+nums[len-1]+nums[len-2]+nums[len-3] < target) continue;
          for(int j = i+1 ;j< len-2 ;j++){
    
    //这里就和 LeetCode 15. 三数之和  一样的原理  唯一多了一个提前判断
              // 这里的三个if与上面同理  
               if(j>i+1&&nums[j]==nums[j-1]) continue;
               if((long)nums[i]+nums[j]+nums[j+1]+nums[j+2] > target) break;
               if((long)nums[i]+nums[j]+nums[len-1]+nums[len-2] < target) continue;
               int left = j+1;
               int right = len-1;
               while(left < right){
    
    
                   long sum =(long) nums[i]+nums[j]+nums[left]+nums[right];
                   if(sum == target) {
    
    
                       zres = new ArrayList<>();//满足要求的子结果集
                       zres.add(nums[i]);
                       zres.add(nums[j]);
                       zres.add(nums[left]);
                       zres.add(nums[right]);
                       res.add(zres);//加入大结果集
                       while(left < right &&nums[left]==nums[left+1]) left++;//两个指针的去重
                       while(left < right &&nums[right]==nums[right-1]) right--;
                       left++;//移动指针到不重复的新区域
                       right--;
                   }else if(sum >target)  right--;//缩小数值
                    else left++;//扩大数值
               }
          }
      }
      return res;
    }
}

おすすめ

転載: blog.csdn.net/weixin_45618869/article/details/132871360