春招打卡d4n06-leetcode刷题15三数之和

118 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

leetcode刷题15三数之和

前文

本文为leetcode双指针类题目,题目序号为15,主要考察内容为在遍历过程中对于遍历方式的优化。

题目信息

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

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

解题思路

根据题目信息可知,该题的目标为在数组中获取到若干数值,使他们的加和为0。面对这种问题,很容易的会想到直接通过遍历进行实现。而改题目中,由于有三个元素,直接进行遍历会具有极高的时间复杂度,显然这不是一种优秀的思路。本题解题方案采取了一个双指针的方式。首先对于数组进行排序,这是为了后续去重校验比较方便,因题目要求不可重复出现结果。然后对数组进行循环,在循环中设置两个指针p和q,用来指示第二及第三个元素的位置。通过第二、三个元素位置的调整,即可得到去重的加和为0的元素。在操作移动的过程中,还要注意当元素前后移动,可能出现完全相同的两个元素,这种情况要继续向前移动。另外,为了方便指针移动,在加和大时移动后一元素,加和小时移动前一元素。这也是排序所带来的后续便利。以上方式即可实现对于该题目的解答。

解题代码

public List<List<Integer>> threeSum(int[] nums) {
    nums = Arrays.stream(nums).sorted().toArray();
    List<List<Integer>> list = new ArrayList<>();
    if(nums.length < 3){
        return list;
    }
    int temp = Integer.MAX_VALUE;
    for (int i = 0; i < nums.length - 2; i++) {
        int p = i + 1;
        int q = nums.length - 1;
        if(nums[i] == temp){
            continue;
        }
        while (true){
            if(p >= q){
                break;
            }
            if(nums[i] + nums[p] + nums[q] == 0){
                List<Integer> item = new ArrayList<>();
                item.add(nums[i]);
                item.add(nums[p]);
                item.add(nums[q]);
                list.add(item);
                int oldQ = q;
                boolean needBreak = true;
                while (p < q){
                    if(nums[q] == nums[oldQ]){
                        oldQ = q;
                        q -= 1;
                    }else{
                        needBreak = false;
                        break;
                    }
                }
                if(needBreak){
                    break;
                }
            }else if(nums[i] + nums[p] + nums[q] < 0){
                int oldP = p;
                boolean needBreak = true;
                while (p < q){
                    if(nums[p] == nums[oldP]){
                        oldP = p;
                        p += 1;
                    }else{
                        needBreak = false;
                        break;
                    }
                }
                if(needBreak){
                    break;
                }
            }else{
                int oldQ = q;
                boolean needBreak = true;
                while (p < q){
                    if(nums[q] == nums[oldQ]){
                        oldQ = q;
                        q -= 1;
                    }else{
                        needBreak = false;
                        break;
                    }
                }
                if(needBreak){
                    break;
                }
            }
        }
        temp = nums[i];
    }
    return list;
}

后记

  • 千古兴亡多少事?悠悠。不尽长江滚滚流。