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;
    }
相关推荐
哎呦没10 分钟前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
编程、小哥哥37 分钟前
netty之Netty与SpringBoot整合
java·spring boot·spring
IT学长编程2 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇2 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码2 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
郭二哈2 小时前
C++——模板进阶、继承
java·服务器·c++
A尘埃3 小时前
SpringBoot的数据访问
java·spring boot·后端
Tisfy3 小时前
LeetCode 2187.完成旅途的最少时间:二分查找
算法·leetcode·二分查找·题解·二分
yang-23073 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
沉登c3 小时前
幂等性接口实现
java·rpc