Leetcode15:三数之和

题目描述

题目解答

这道题采用双指针的解法,先遍历一边数组,然后在每次循环里新建两个左右指针,之后

通过两个指针逐渐逼近,来寻找唯一的解

java 复制代码
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        // 结果集:一个"装整数列表的列表",没找到答案时它自然就是空的
        List<List<Integer>> result = new ArrayList<>();

        // 第一步:排序。
        // 作用1:让双指针移动有方向性(偏小左指针右移,偏大右指针左移)
        // 作用2:让相同的数相邻,去重才有依据
        Arrays.sort(nums);

        // 外层循环:枚举三元组中的第一个数 A。
        // i 最多到 nums.length - 3,保证 A 后面还至少留两个位置给 B 和 C
        for (int i = 0; i < nums.length - 2; i++) {
            // 剪枝:数组已排序,nums[0] 是最小值,
            // 最小值都大于 0 说明全是正数,不可能凑出 0,直接返回空结果
            if (nums[0] > 0) {
                return new ArrayList<>();
            }

            // 对 A 去重:当前数和上一轮的 A 相同,说明这一轮
            // 只会重复上一轮的搜索结果(搜索范围还是其子集),整轮跳过。
            // i >= 1 的保护条件放左边,保证 i = 0 时不会去访问 nums[-1] 越界
            if (i >= 1 && nums[i] == nums[i - 1]) {
                continue;
            }

            // 双指针:left 从 A 的下一个位置出发找 B,right 从末尾出发找 C
            int left = i + 1;
            int right = nums.length - 1;

            while (left < right) {
                if (nums[i] + nums[left] + nums[right] < 0) {
                    // 三数之和偏小:左指针右移,换一个更大的 B 试试
                    left++;
                } else if (nums[i] + nums[left] + nums[right] > 0) {
                    // 三数之和偏大:右指针左移,换一个更小的 C 试试
                    right--;
                } else {
                    // 三数之和恰好为 0,收获一组答案
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));

                    // 对 B 去重:下一个 left 的值和当前相同,滑过去不重复计算。
                    // left < right 防止指针交叉时访问越界
                    while (left < right && nums[left] == nums[left + 1]) {
                        left++;
                    }

                    // 对 C 去重:同理,跳过右边连续相同的值
                    while (left < right && nums[right] == nums[right - 1]) {
                        right--;
                    }

                    // 收获答案后两个指针必须一起动:
                    // 只动一个指针,和就偏离了目标值,找不到新解,
                    // 遇到重复值时还会收获重复答案
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
}
相关推荐
小羊没烦恼!1 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
俊昭喜喜里1 天前
java中的继承和多态的区别
java
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕1 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码1 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖1 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时1 天前
01-06-A-JVM排查实战详解
java·jvm
猎头南楼1 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
vipxieliang1 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot