【LeetCode-15】三数之和


🎉 关注“青柠代码录公众号,🔥更多精彩内容持续更新中🔥,快来加入我们吧!🚀


LeetCode题目链接:

15. 三数之和 - 力扣(LeetCode)


目录

📑 文章摘要

🔍 详细解题思路

🛠️ 详细案例执行过程

📝 示例 1

📝 示例 2

📝 示例 3

🖥️ Java代码实现

📊 总结


📑 文章摘要

在本篇博客中,我们将深入探讨如何解决经典的“三数之和”问题。通过详细的解题思路、清晰的代码实现以及丰富的案例分析,帮助读者全面理解算法设计的核心逻辑。无论你是初学者还是进阶开发者,本文都将为你提供有价值的参考。


🔍 详细解题思路

🧩 问题背景

给定一个整数数组 nums,我们需要找到所有满足以下条件的三元组 [nums[i], nums[j], nums[k]]

  1. 索引不同i != ji != k,且 j != k

  2. 和为零nums[i] + nums[j] + nums[k] == 0

  3. 去重:返回的结果中不能包含重复的三元组。

💡 核心思想

要高效地解决这个问题,我们可以采用以下步骤:

  1. 排序:首先对数组进行排序,便于后续操作。

  2. 固定一个数:遍历数组,固定一个数作为目标值。

  3. 双指针法:利用双指针快速查找剩余两个数,使得三数之和为零。

  4. 去重处理:在每一步中,跳过重复的数字,避免结果集中出现重复的三元组。

这种方法的时间复杂度为 O(n²),比暴力枚举的 O(n³) 更加高效。


🛠️ 详细案例执行过程

📝 示例 1

输入:nums = [-1, 0, 1, 2, -1, -4]

第一步:排序

将数组排序后得到:[-4, -1, -1, 0, 1, 2]

第二步:固定第一个数

固定 nums[0] = -4,使用双指针查找剩余两数。

  • 左指针指向 -1,右指针指向 2

  • 计算和:-4 + (-1) + 2 = -3,小于零,移动左指针。

  • 左指针指向下一个 -1,计算和:-4 + (-1) + 2 = -3,仍然小于零,继续移动左指针。

  • 左指针指向 0,计算和:-4 + 0 + 2 = -2,依然小于零,继续移动左指针。

  • 左指针指向 1,计算和:-4 + 1 + 2 = -1,小于零,移动左指针。

  • 左指针越界,结束当前循环。

固定 nums[1] = -1,使用双指针查找剩余两数。

  • 左指针指向 -1,右指针指向 2

  • 计算和:-1 + (-1) + 2 = 0,符合条件,记录结果 [-1, -1, 2]

  • 移动左指针和右指针,跳过重复数字。

  • 左指针指向 0,右指针指向 1

  • 计算和:-1 + 0 + 1 = 0,符合条件,记录结果 [-1, 0, 1]

  • 移动左指针和右指针,结束当前循环。

固定 nums[2] = -1,由于与前一个数相同,直接跳过。

固定 nums[3] = 0,使用双指针查找剩余两数。

  • 左指针指向 1,右指针指向 2

  • 计算和:0 + 1 + 2 = 3,大于零,移动右指针。

  • 右指针越界,结束当前循环。

最终结果

[[-1, -1, 2], [-1, 0, 1]]

📝 示例 2

输入:nums = [0, 1, 1]

第一步:排序

排序后得到:[0, 1, 1]

第二步:固定第一个数

固定 nums[0] = 0,使用双指针查找剩余两数。

  • 左指针指向 1,右指针指向 1

  • 计算和:0 + 1 + 1 = 2,大于零,移动右指针。

  • 右指针越界,结束当前循环。

最终结果

[]

📝 示例 3

输入:nums = [0, 0, 0]

第一步:排序

排序后得到:[0, 0, 0]

第二步:固定第一个数

固定 nums[0] = 0,使用双指针查找剩余两数。

  • 左指针指向 0,右指针指向 0

  • 计算和:0 + 0 + 0 = 0,符合条件,记录结果 [0, 0, 0]

  • 移动左指针和右指针,结束当前循环。

最终结果

[[0, 0, 0]]

🖥️ Java代码实现

以下是基于上述思路的完整Java代码实现:

import java.util.*;
​
class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        // 结果集
        List<List<Integer>> result = new ArrayList<>();
        
        // 排序数组
        Arrays.sort(nums);
        
        // 遍历数组,固定第一个数
        for (int i = 0; i < nums.length - 2; i++) {
            // 跳过重复的第一个数
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            // 双指针初始化
            int left = i + 1, right = nums.length - 1;
            
            // 双指针查找剩余两数
            while (left < right) {
                int sum = nums[i] + nums[left] + nums[right];
                
                if (sum == 0) {
                    // 找到符合条件的三元组
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    
                    // 跳过重复的左指针和右指针
                    while (left < right && nums[left] == nums[left + 1]) left++;
                    while (left < right && nums[right] == nums[right - 1]) right--;
                    
                    // 移动指针
                    left++;
                    right--;
                } else if (sum < 0) {
                    // 和小于零,移动左指针
                    left++;
                } else {
                    // 和大于零,移动右指针
                    right--;
                }
            }
        }
        
        return result;
    }
}

📊 总结

通过本文的学习,我们掌握了如何高效解决“三数之和”问题。核心在于排序与双指针的结合,以及对重复元素的巧妙处理。希望这篇文章能为你带来启发,并助力你在算法学习的道路上更进一步!🌟


如果你有任何疑问或建议,欢迎在评论区留言讨论!💬

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青柠代码录

您的鼓励是我最大的动力 '◡'

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值