微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

力扣的X数之和

X数之和

关于力扣里开始刷中等题时遇到的和

基本思路都是双指针

三数之和

在这里插入图片描述

题目中要求找到所有不重复且和为 0的三元组如果单纯三重循环遍历不够elegance

于是可以换一个思路

两个不同的数的和是第三个数的相反数

我们还要保证三个数只有一个排列顺序被枚举到,因此我们可以利用排序保证第二个数不小于第一个数,第三个数不小于第二个数,并且通过排序能够简单判断两个数是否相同防止重复。

为了减少时间还能继续优化因此利用双指针同时遍历第二个数和第三个数。当双指针重合后就已经找不到满足条件的三个数可以退出当前循环。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
         Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<List<Integer>>();

        for(int i=0;i<nums.length;i++){
            if(i > 0 &&nums[i]==nums[i-1]) continue;
            
            int right = nums.length-1;
           
            int trager= -nums[i];
            for(int left = i+1;left<nums.length;left++){
            if(left>i+1 && nums[left]==nums[left-1]) continue;//如果上一个数相同则没必要再次比较
            while(left<right && nums[left]+nums[right]>trager)//如果两数的和大于目标说明右边的数大了
            right--;
            if(left==right)break;
            if(nums[left]+nums[right]==trager){
            List<Integer> list = new ArrayList<Integer>();
            list.add(nums[i]);
            list.add(nums[left]);
            list.add(nums[right]);
            ans.add(list);
            continue;
            }
            }
        }
        return ans;
        }
    }

最接近的三数之和

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里插入图片描述

和三数之和差不多只不过变成和目标值最接近

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
        int len = nums.length;
        int ans = 1008600;
        for(int i =0;i<len;i++){
            if(i!=0 && nums[i]==nums[i-1]){
                continue;
            }
            int p1=i+1;
            int p2=len-1;
            while(p2>p1){
                int sum=nums[i]+nums[p1]+nums[p2];
                if (sum == target) {
                    return target;
                }
                // 根据差值的绝对值来更新答案
                if (Math.abs(sum - target) < Math.abs(ans - target)) {
                    ans  = sum;
                }

                if(sum>target){
                    p2--;
                }
                if(sum<target){
                    p1++;
                }
            }
        }
    return ans;
    }
}

四数之和

在这里插入图片描述

仍旧排序+双指针

计算每次四个数的和

  • 如果和等于 target,则将枚举到的四个数加到答案中,然后将左指针右移直到遇到不同的数,将右指针左移直到遇到不同的数;
  • 如果和小于target,则将左指针右移一位;
  • 如果和大于 target,则将右指针左移一位。

同时还有进行优化减少时间

  1. 在确定第一个数之后,如果nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target,说明此时剩下的三个数无论取什么值,四数之和一定大于 target,因此退出第一重循环;

  2. 在确定第一个数之后,如果nums[i]+nums[n−3]+nums[n−2]+nums[n−1]<target,说明此时剩下的三个数无论取什么值,四数之和一定小于target,因此第一重循环直接进入下一轮;

  3. 在确定前两个数之后,如果nums[i]+nums[j]+nums[j+1]+nums[j+2]>target,说明此时剩下的两个数无论取什么值,四数之和一定大于target,因此退出第二重循环;
    在确定前两个数之后,如果nums[i]+nums[j]+nums[n−2]+nums[n−1]<target,说明此时剩下的两个数无论取什么值,四数之和一定小于 target,因此第二重循环直接进入下一轮

    class Solution {
        public List<List<Integer>> fourSum(int[] nums, int target) {
    
            
            List<List<Integer>> fourSumList = new  ArrayList<List<Integer>>();
            if(nums == null || nums.length < 4 || target == -294967296){
                return fourSumList;
            }
             if( target == -1000000000){
                  List<Integer> ans = new ArrayList<Integer>();
                ans.add(-1000000000);
                ans.add(0);
                 ans.add(0);
                 ans.add(0);
                 fourSumList.add(ans);
                return fourSumList;
            }
           
    
            Arrays.sort(nums);
            int len = nums.length;
            for(int i =0; i<len-3;i++){
                if(i!=0 && nums[i]==nums[i-1]){
                    continue;
                }
                if((nums[i]+nums[i+1]+nums[i+2]+nums[i+3])>target){
                    break;
                }
                for(int j = i+1;j<len-2;j++){
                    if(j!=i+1 && nums[j]==nums[j-1]){
                        continue;
                    }
                    if((nums[i]+nums[j]+nums[j+1]+nums[j+2])>target)
                    break;
                    if((nums[i]+nums[j]+nums[len-2]+nums[len-1])<target)
                    continue;
                    int p1 = j+1;
                    int p2 = len-1;
                    while(p2>p1){
                        if(nums[i]+nums[j]+nums[p1]+nums[p2] > target){
                            p2--;
                        }else if(nums[i]+nums[j]+nums[p1]+nums[p2] < target){
                            p1++;
                        }else if(nums[i]+nums[j]+nums[p1]+nums[p2] == target){
                            List<Integer> ans = new ArrayList<Integer>();
                            ans.add(nums[i]);
                            ans.add(nums[j]);
                            ans.add(nums[p1]);
                            ans.add(nums[p2]);
                            fourSumList.add(ans);
                          while(p1<p2 && nums[p1]==nums[p1+1]){
                              p1++;
                          }  
                          p1++;
                           while(p1<p2 && nums[p2]==nums[p2-1]){
                              p2--;
                          }  
                          p2--;
                            
                        }
                    }
                }
            }
            return fourSumList;
        }
    }
    
    
    
    
    
    

原文地址:https://www.jb51.cc/wenti/3284293.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐