leetcode 数组Ⅳ 2021-02-20

leetcode 数组Ⅳ 2021-02-20

寻找两个正序数组的中位数(困难)1

三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例 2:

输入:nums = []
输出:[]

示例 3:

输入:nums = [0]
输出:[]

最开始的思路是先排序,和为0只有两种情况,一种是相反数+0,另外一种是三个非0的数和为0,也就是说两个正数的和为负数的相反数或两个负数的和为正数数的相反数,分这两种情况求出即可。当代码相当麻烦。

通过评论学习了双指针的方法,更加方便。

public static List<List<Integer>> threeSumA(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        //排序
        Arrays.sort(nums);
        //双指针
        int len = nums.length;
        for(int i = 0;i < len;++i) {
            if(nums[i] > 0) return lists;

            //当前位置与上一位相等时则跳过
            if(i > 0 && nums[i] == nums[i-1]) continue;
            
            int curr = nums[i];
            int L = i+1, R = len-1;
            while (L < R) {
                int tmp = curr + nums[L] + nums[R];
                if(tmp == 0) {  //等于0 符合要求
                    List<Integer> list = new ArrayList<>();
                    list.add(curr);
                    list.add(nums[L]);
                    list.add(nums[R]);
                    lists.add(list);
                    while(L < R && nums[L+1] == nums[L]) ++L; //让指针移动的下一位与当前位置不相等,下同
                    while (L < R && nums[R-1] == nums[R]) --R;
                    ++L;
                    --R;
                } else if(tmp < 0) { //小于0 说明nums[L] + nums[R]小了,L++
                    ++L;
                } else {             //大于0 说明nums[L] + nums[R]大了,R++
                    --R;
                }
            }
        }
        return lists;
    }
    

    //很垃圾的代码,思路是先求有相反数的情况,再求两个整数加一个负数和两个负数加一个正数的情况。居然没超时
    public static List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        if( nums.length < 3){
            return lists;
        }

        if( nums.length == 3 ){
            if( nums[0] + nums[1] + nums[2] == 0){
                List<Integer> list = new ArrayList<>();
                list.add(nums[0]);
                list.add(nums[1]);
                list.add(nums[2]);
                lists.add(list);
            }
            return lists;
        }

        Arrays.sort(nums);
        if( nums[0] >= 0  || nums[nums.length-1] <= 0){
            if( nums[0] + nums[1] + nums[2] == 0 || nums[nums.length-1] + nums[nums.length-2] + nums[nums.length-3] == 0){
                List<Integer> list = new ArrayList<>();
                list.add(0);
                list.add(0);
                list.add(0);
                lists.add(list);
            }
            return lists;
        }

        Map<Integer,Integer> map = new HashMap();
        int change = 0;
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i],i);
            if(nums[i] < 0 &&  nums[i+1] >= 0){
                change = i ;
            }
        }
        if(nums.length > change + 3){
            if( nums[change+1] + nums[change+2] + nums[change+3] == 0){
                List<Integer> list = new ArrayList<>();
                list.add(nums[change+1]);
                list.add(nums[change+2]);
                list.add(nums[change+3]);
                if(!lists.contains(list)){
                    lists.add(list);
                }
            }
        }
        for (int i = nums.length - 1; i > change; i--) {
            if(nums[i] <= 0 ){
                break;
            }
            if(nums[change + 1] == 0){
                if(map.containsKey(-nums[i])){
                    List<Integer> list = new ArrayList<>();
                    list.add(-nums[i]);
                    list.add(0);
                    list.add(nums[i]);
                    if(!lists.contains(list)){
                        lists.add(list);
                    }
                }
            }
            if(Math.abs(nums[0]) >= nums[i]){
                for (int j = i - 1; j > change; j--) {
                    if(nums[j] <= 0 ){
                        break;
                    }
                    if(map.containsKey(-(nums[i]+nums[j]))){
                        List<Integer> list = new ArrayList<>();
                        list.add(nums[i]);
                        list.add(nums[j]);
                        list.add(-(nums[i]+nums[j]));
                        if(!lists.contains(list)){
                            lists.add(list);
                        }
                    }
                }

            }
            for (int j = 0; j <= change; j++) {
                if(map.containsKey(-(nums[i]+nums[j])) && map.get(-(nums[i]+nums[j])) >j && map.get(-(nums[i]+nums[j])) <= change){
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[j]);
                    list.add(-(nums[i]+nums[j]));
                    if(!lists.contains(list)){
                        lists.add(list);
                    }
                }
            }

        }

        return lists;
    }

在这里插入图片描述


  1. 来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/3sum
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值