《算法通关村—三数和为零问题解析》

自用

public class ThreeSum {
    //找出所有和为0且不重复的三元组
    public List<List<Integer>> threeSum(int[] nums){
        //数组长度
        int n = nums.length;
        //将数组排序
        Arrays.sort(nums);
        //third指针指向数组末尾
        int third = n-1;
        //装载三元组的容器
        List<List<Integer>> ans = new ArrayList<List<Integer>>() ;
        //最外层循环,遍历数组中的每一个元素
        for (int first = 0; first < n; first++) {
            //num[first] == nums[first-1]能够去掉重复的三元组,为什么呢
            //因为如果num[first-1]=1,遍历它时找到了三元组{1,0,-1},那么遍历nums[first]同样也会得到这个三元组
            //所以如果前后两个元素相同就直接跳过当前元素就好了
            if(first>0 && nums[first]  == nums[first-1]){
                continue;
            }
            //下面nums[second] + nums[third] >target再讲为什么是-nums[first]
            int target = -nums[first];
            //内层循环从fist的下一个元素开始遍历
            for (int second = first; second < n; second++) {
                //与上面一样,去重,去遍历下一个元素
                if(second >first +1 && nums[second] == nums[second-1]){
                    continue;
                }
                //因为数组是排过序的,所以nums[third]就是数组中最大的数,而target是三元组中第一个数的相反数 target = -nums[first]
                //如果nums[second] + nums[third] == target,那么此时nums[second] + nums[third] + nums[first]不就为0了吗
                //为什么要nums[second] + nums[third] >target呢?因为nums[third]已经是最大的数了,所以我们让third向前遍历
                //这样才有可能让nums[second] + nums[third] == target
                while(second < third && nums[second] + nums[third] >target){
                    third--;
                }
                //为什么second==third就退出整个for循环进行下次first遍历
                // 而不是像上面那样用continue结束本次循环然后遍历下一个second呢
                //我们先分析为什么会second == third,出现这种情况只有nums[second] + nums[third] >target
                //因为只有nums[second] + nums[third] >target才能进入上面的while循环,让thrid--到和second相同
                //说明直到second==third也没能让nums[second] + nums[third] = target
                //那还有种情况就是当second==third时,nums[second] + nums[third] = target怎么没有考虑呢
                //这时second==third指向同一个位置,如果这也算的话那不就返回一个两元组了吗
                //回到最初的问题,为什么是break而不是continue?
                //举个简单的例子  1+5>2 1+4>2 1+3>2... 1相当于second 5相当于third 然后因为nums[second] + nums[third] >target,所以它一直在--
                //那如果此时是continue的话就会遍历到下一个second 此时会变成 3+5>2 ,可以发现最小的third都无法满足条件,你继续增加second的值就更不可能满足了
                //所以后面的second就没有必要遍历了
                if (second == third){
                    break;
                }
                if(nums[first] + nums[second] +nums[third] == 0){
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[first]);
                    list.add(nums[second]);
                    list.add(nums[third]);
                    ans.add(list);
                }
            }
        }
        return ans;
    }

    public static void main(String[] args) {
        ThreeSum ts = new ThreeSum();
        int[] nums = {-3,2,4,0,-2,-1,1};
        List<List<Integer>> lists = ts.threeSum(nums);
        for (List<Integer> list : lists) {
            System.out.println(list);

        }
    }
}

方法中判断条件的解析已写在代码中

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值