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;
    }
}
相关推荐
leobertlan6 小时前
痛苦系列 | DSP-03 跨越单位圆:Z变换与零极点分析
算法·程序员
蛋蛋的就会顺顺的6 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
需要8267 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
开发小能手1237 小时前
答案daanC语言
数据结构·算法
小 黄 鸡7 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
Navigator_Z9 小时前
LeetCode //C - 1291. Sequential Digits
c语言·算法·leetcode
伯恩bourne9 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
silvamux_9 小时前
curl 测试 OpenAI 兼容 API 的完整流程
java·人工智能·缓存·ai·oneapi
pride.li10 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
省钱兄--zs10 小时前
深圳24小时自助健身房软硬件解决方案实战指南与开发流程详解
java·数据仓库·spring boot·小程序·架构