两、三、四数之和

两次遍历就不写了,这里写双指针做法:
 

class Data implements Comparable{
    int num;
    int index;
    Data(int num, int index){
        this.num = num;
        this.index = index;
    }

    @Override
    public int compareTo(Object o) {
        if(this.num < ((Data) o).num){
            return -1;
        }else if(this.num == ((Data)o).num){
            return 0;
        }else{
            return 1;
        }
    }
}

class Solution {

    int []res = new int[2];

    public int[] twoSum(int[] nums, int target) {
        // 双指针
        int left = 0;
        int right = nums.length-1;
        List<Data> ls = new ArrayList<>();
        for(int i=0; i<nums.length; i++){
            Data data = new Data(nums[i], i);
            ls.add(data);
        }
        Collections.sort(ls);

        while(left < right){
            if(ls.get(left).num + ls.get(right).num < target){
                left++;
                continue;
            }
            if(ls.get(left).num + ls.get(right).num > target){
                right--;
                continue;
            }
            res[0] = ls.get(left).index;
            res[1] = ls.get(right).index;
            break;
        }

        return res;
    }
}

 三指针:固定死一个,其他的走

class Solution {

    List<List<Integer>> res = new LinkedList<>();
    Set<List<Integer>> set = new HashSet<>();
    public List<List<Integer>> threeSum(int[] nums) {

        // 三指针
        int left = 0;
        int right = nums.length-1;
        int mid = 0;

        // 排序
        Arrays.sort(nums);
        while(mid < nums.length){
            while(left < right){
                if(left == mid){
                    left+=1;
                    continue;
                }
                if(right == mid){
                    right--;
                    continue;
                }
                if(nums[left] + nums[mid] + nums[right] < 0){
                    left++;
                    continue;
                }
                if(nums[left] + nums[mid] + nums[right] > 0){
                    right--;
                    continue;
                }
                List<Integer> ls = new LinkedList<>();
                if(mid < left){
                    ls.add(nums[mid]);
                    ls.add(nums[left]);
                    ls.add(nums[right]);
                }else if(mid > left && mid < right){
                    ls.add(nums[left]);
                    ls.add(nums[mid]);
                    ls.add(nums[right]);
                }else if(mid > right){
                    ls.add(nums[left]);
                    ls.add(nums[right]);
                    ls.add(nums[mid]);
                }
            
                set.add(ls);
                left++;
                right--;
                //break;
            }
            left = 0;
            right = nums.length-1;
            mid++;
        }
        for(List lls: set){
            res.add(lls);
        }
        return res;
    }
}

 同样使用的三指针......

class Solution {
    public int threeSumClosest(int[] nums, int target) {
        // 三指针
        int left = 0;
        int mid = 0;
        int right = nums.length-1;
        Arrays.sort(nums);
        int res = 0;
        int mv = Integer.MAX_VALUE;
        while(mid < nums.length){
            while(left < right){
                if(left == mid){
                    left++;
                    continue;
                }
                if(right == mid){
                    right--;
                    continue;
                }
                if(Math.abs(nums[left] + nums[mid] + nums[right] - target) < mv){
                    res = nums[left] + nums[mid] + nums[right];
                    mv = Math.abs(nums[left] + nums[mid] + nums[right] - target);
                }
                if(nums[left] + nums[mid] + nums[right] - target > 0){
                    right--;
                    continue;
                }
                if(nums[left] + nums[mid] + nums[right] - target < 0){
                    left++;
                    continue;
                }
                if(nums[left] + nums[mid] + nums[right] - target == 0){
                    return target;
                }
            }
            left = 0;
            right = nums.length-1;
            mid++;
        }
       // System.out.println(res);
        return res;
    }
}

看题解说,三指针的基础上再来一层for循环就能解决,但是我还是用了递归去做:

但凡少一个判断,或判断写的不对,剪枝有问题,就会超时......

class Solution {

    List<List<Integer>> res = new LinkedList<>();
    Set<LinkedList<Integer>> set = new HashSet<>();

    private void dfs(int []nums, int target, int n, int index, LinkedList<Integer> ls, int sum, boolean sign[]){
        
        // 如果换成 n > 4 return 会超时
        if(n == 4 && sum != target){
            return;
        }

        if(n == 4 && sum == target){
            set.add(new LinkedList<>(ls));
            return;
        }

        for(int i=index; i<nums.length; i++){
            // 不加下面的剪枝会超时
            if(nums[i] > 0 && sum >= target){
                break;
            }
            if(sign[i]){
                continue;
            }
            sign[i] = true;
            ls.addLast(nums[i]);
            dfs(nums, target, n+1,  i, ls, sum+nums[i], sign);
            ls.removeLast();
            sign[i] = false;
        }
    }

    public List<List<Integer>> fourSum(int[] nums, int target) {

        // 保证不重复
        Arrays.sort(nums);

        LinkedList<Integer> ls = new LinkedList<>();
        boolean sign[] = new boolean[nums.length];
        dfs(nums, target, 0, 0, ls, 0, sign);

        for(LinkedList lks: set){
            res.add(lks);
        }
        return res;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值