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;
    }
相关推荐
腥臭腐朽的日子熠熠生辉39 分钟前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian41 分钟前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之1 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码1 小时前
Spring Task 定时任务
java·前端·spring
俏布斯1 小时前
算法日常记录
java·算法·leetcode
27669582921 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息1 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen2 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算
脑子慢且灵2 小时前
蓝桥杯冲刺:一维前缀和
算法·leetcode·职场和发展·蓝桥杯·动态规划·一维前缀和
松韬2 小时前
Spring + Redisson:从 0 到 1 搭建高可用分布式缓存系统
java·redis·分布式·spring·缓存