【2022初春】【笔记】NSum问题

2Sum无序,2Sum有序;3Sum,Nsum 模板
3Sum和Nsum的关键是增加start位置

package demo;

import java.util.*;

public class NSum {


    public static void main(String[] args){
        //Scanner sc = new Scanner(System.in);
        int[] nums = new int[]{-1,0,1,2,-1,-2,0};
        int target = 0;
        /*int[] ans = twoSum1(nums,6);
        int[] ans = twoSum2(nums,9);
        for(int a : ans){
            System.out.println(a);
        }*/
        //ArrayList<ArrayList<Integer>> ans = twoSum3(nums,target);
        //ArrayList<ArrayList<Integer>> ans = threeSum(nums,target);
        Arrays.sort(nums);
        ArrayList<ArrayList<Integer>> ans = nSum(nums,4,0,target);
        System.out.println(ans);
    }

    //nSum 所有不重复结果
    //nums 数组; n nSum; start 数组开始位置
    static ArrayList<ArrayList<Integer>> nSum(int[] nums, int n, int start, int target){
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(n<2||nums.length<n) return res;
        if(n==2){
            int lo = start, hi = nums.length-1;
            while(lo<hi){
                int sum = nums[lo] + nums[hi];
                int left = nums[lo], right = nums[hi];
                if(sum<target) while(lo<hi&&nums[lo]==left) lo++;
                if(sum>target) while(lo<hi&&nums[hi]==right) hi--;
                if(sum==target){
                    ArrayList<Integer> cnt = new ArrayList<>();
                    cnt.add(left);
                    cnt.add(right);
                    res.add(cnt);
                    while(lo<hi&&nums[lo]==left) lo++;
                    while(lo<hi&&nums[hi]==right) hi--;
                }
            }
        }else {
            for(int i=start; i<nums.length; i++){
                ArrayList<ArrayList<Integer>> tmp = nSum(nums,n-1,i+1,target-nums[i]);
                for(ArrayList<Integer> a : tmp){
                    a.add(nums[i]);
                    res.add(a);
                }
                while(i<nums.length-1&&nums[i]==nums[i+1]) i++;
            }
        }
        return res;
    }

    //3Sum 所有不重复结果
    static ArrayList<ArrayList<Integer>> threeSum(int[] nums, int target){
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        for(int i=0; i<nums.length; i++){
            ArrayList<ArrayList<Integer>> cnt = twoSum(nums,i+1,target-nums[i]);
            for(ArrayList<Integer> a : cnt){
                a.add(nums[i]);
                res.add(a);
            }
            while(i<nums.length-1&&nums[i]==nums[i+1]) i++;
        }
        return res;
    }
    //2Sum 调用模板
    static ArrayList<ArrayList<Integer>> twoSum(int[] nums, int start,int target){
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        int lo = start,hi = nums.length-1;
        while (lo<hi){
            int sum = nums[lo] + nums[hi];
            int left = nums[lo], right = nums[hi];
            if(sum<target) while(lo<hi&&nums[lo]==left) lo++;
            if(sum>target) while(lo<hi&&nums[hi]==right) hi--;
            if(sum==target){
                ArrayList<Integer> cnt = new ArrayList<>();
                cnt.add(left);
                cnt.add(right);
                res.add(cnt);
                while(lo<hi&&nums[lo]==left) lo++;
                while(lo<hi&&nums[hi]==right) hi--;
            }
        }
        return res;
    }

    //排序2Sum记录所有不重复结果
    static ArrayList<ArrayList<Integer>> twoSum3(int[] nums, int target){
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        int lo = 0,hi = nums.length-1;
        while (lo<hi){
            int sum = nums[lo] + nums[hi];
            int left = nums[lo], right = nums[hi];
            if(sum<target) while(lo<hi&&nums[lo]==left) lo++;
            if(sum>target) while(lo<hi&&nums[hi]==right) hi--;
            if(sum==target){
                ArrayList<Integer> cnt = new ArrayList<>();
                cnt.add(left);
                cnt.add(right);
                res.add(cnt);
                while(lo<hi&&nums[lo]==left) lo++;
                while(lo<hi&&nums[hi]==right) hi--;
            }
        }
        return res;
    }

    //排序2Sum,双指针
    static int[] twoSum2(int[] nums, int target){
        Arrays.sort(nums);
        int lo = 0,hi = nums.length-1;
        int[] res = {-1,-1};
        while(lo<hi){
            int sum = nums[lo] + nums[hi];
            if(sum<target) lo++;
            if(sum>target) hi--;
            if(sum==target){
                res[0] = nums[lo];
                res[1] = nums[hi];
                return res;
            }
        }
        return res;
    }

    //无序数组2Sum
    //可以但存疑,用HashMap存重复的数字为什么可以
    static int[] twoSum1(int[] nums, int target){
        Map<Integer,Integer> map = new HashMap<>();
        for(int i=0; i<nums.length; i++){
            map.put(nums[i],i);
        }
        int[] res = new int[2];
        for(int i=0; i<nums.length; i++){
            int cnt = target - nums[i];
            if(map.containsKey(cnt)&&map.get(cnt)!=i){
                res[0] = nums[i];
                res[1] = cnt;
            }
        }
        return res;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值