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;
    }
}
相关推荐
Nolla16 分钟前
为什么 assertThrows 需要 () ->:Lambda 延迟执行与异常捕获
java
黄金龙PLUS18 分钟前
ASCON置换算法的优缺点
算法·网络安全·密码学·哈希算法·同态加密
SL_staff19 分钟前
风控规则不该写代码:一个开发者视角的规则引擎实践拆解
java·架构·全栈
邪修king23 分钟前
Re:Linux 系统篇(十六):进程篇(五):O (1) 调度算法深度解析 —— 优先级数组、位图优化与活跃 / 过期双队列
linux·运维·算法
Yfhonier40 分钟前
6440. 极大连通图个数(DFS)
数据结构·算法·深度优先
xieliyu.43 分钟前
计算机网络|数据链路层详解:MAC 地址、交换机、ARP 协议、CRC 校验
java·网络·笔记·计算机网络·java-ee
Rnan-prince1 小时前
从 Bitmap、BloomFilter到 Count-Min Sketch:三个数据结构,一条“用误差换空间“的演进线
数据结构·sketch·bitmap
SimonKing1 小时前
手机投屏到电脑,不用装任何 App,这个开源工具免费搞定:QtScrcpy
java·后端·程序员