Java【手撕双指针】LeetCode 15. “三数之和“, 图文详解思路分析 + 代码

文章目录


前言

各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你:

📕 JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统等

📗 Java数据结构: 顺序表, 链表, 堆, 二叉树, 二叉搜索树, 哈希表等

📘 JavaEE初阶: 多线程, 网络编程, TCP/IP协议, HTTP协议, Tomcat, Servlet, Linux, JVM等(正在持续更新)

一、三数之和

1, 题目

OJ链接

这题是在"两数之和"的基础上进行了一些提升, 核心算法思想是一致的, 不熟悉 "两数之和" 这道题的小伙伴建议看一下 这道题的分析 会对本题的理解有很大帮助


2, 思路分析

最简单的暴力枚举 : 三层 for 循环, 从先固定一个数, 在剩余区间上固定一个数, 暴力枚举依次找第三个数, 判断这三个数的和是否为 0 (目标值), 时间复杂度为O(N³), 必然会超出时间限制

我们已经有了 两数之和 这道题的基础, 那完全可以 :

  1. 先对数组排序(有序后使用对撞双指针可以大大提高效率)
  2. 使用 i 指针先固定一个数
  3. 在剩余区间上使用 "两数之和" 的解法找到另外两个数

注意, 这个 target 的值, 在本题中应该是 0 - i 下标的值
还需要注意, 题中要求找到不重复的三个数, 所以需要进行去重操作

  1. 当 left 和 right 指针找到符合条件的两个数后, left++, right--, 但还需要 left 判断当前 left 是否等于下一个 left , right 判断当前 right 是否等于下一个 right, 如果等于, 要对 left / right 去重
  2. 当 i++ 之后需要判断当前这个 i 是否和刚才的值相等, 如果相等, 要对 i 去重
  • 初始位置 i 指向 0 下标
  • i 指向 0 下标时, 使用双指针遍历完了剩余区间, 让 i++

  • i 指向 1 下标时, 使用双指针遍历完了剩余区间, 让 i++, 此时 i 到了 2 下标, 和 i 在 1 下标时的值相等, i 继续自增(去重)

    后续步骤省略

3, 代码

java 复制代码
	public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> list = new ArrayList<>();
        Arrays.sort(nums);
        int i = 0;
        while(i < nums.length - 2) {
            if(nums[i] > 0) {
                return list;
            }
            int target = 0 - nums[i];
            int left = i + 1;
            int right = nums.length - 1;
            while(left < right) {
                List<Integer> inList = new ArrayList<>();
                if(nums[left] + nums[right] > target) {
                    right--;
                }else if(nums[left] + nums[right] < target) {
                 
                    left++;
                }else {
                    while(left < right && nums[right] == nums[right - 1]) {
                        right--;
                    }
                    while(left < right && nums[left] == nums[left + 1]){
                        left++;
                    }
                    inList.add(nums[i]);
                    inList.add(nums[left]);
                    inList.add(nums[right]);
                    list.add(inList);
                    left++;
                    right--;
                }
            }
            i++;
            while(nums[i] == nums[i - 1] && i < nums.length - 2) {
                i++;
            }
        }
        return list;
    }
相关推荐
passer__jw76726 分钟前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
代码之光_198026 分钟前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi32 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
StayInLove1 小时前
G1垃圾回收器日志详解
java·开发语言
对许1 小时前
SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“
java·log4j
无尽的大道1 小时前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
小鑫记得努力1 小时前
Java类和对象(下篇)
java
binishuaio1 小时前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE1 小时前
【Java SE】StringBuffer
java·开发语言
老友@1 小时前
aspose如何获取PPT放映页“切换”的“持续时间”值
java·powerpoint·aspose