LeetCode100之三数之和(15)--Java

news2024/11/5 18:44:39

1.问题描述

        给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

        注意

        答案中不可以包含重复的三元组

        示例1

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

        示例2 

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

        示例3 

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

        提示

  • 3 <= nums.length <= 3000
  • -105 <= nums[i] <= 105

        难度等级

             中等

        题目链接

             三数之和

2.解题思路

        这道题叫做三数之和,可以看做两数之和的升级版,不过我没办法用两数之和的hash方法来做了。这一次,我选择了双指针遍历。可能你会疑惑,不是三数之和吗?怎么是双指针法,其实我们只要把其中一个数固定下来,那不就是回归两个数了吗?两个数当然就是双指针法了。

        首先,我们得定义一个List集合来存储结果,还要对数组进行排序(使用双指针法的前提)。

    //用来存储结果
    List<List<Integer>> result = new ArrayList<>();

        接着,我们就可以开始数组的遍历了。for循环先固定第一个数,这里固定数也是有讲究的,因为它要求的是三个数和为0。我们已经对数组进行排序了,所以小的数肯定在前面,大的数肯定在后面,如果我们的第一个数就已经大于0了,那么后面两个数必定大于0,也就不可能三个数相加为0,所以直接结束就好了。

        //第一个数就大于0,那三个数不可能加起来和为0
        if(nums[i] > 0){
            break;
        }

        如果,第一个数小于0且索引不为0(防止数组越界)的话,因为题目告诉我们不包含重复的三元组,所以我们的第一个数要跳过已经使用过的数。又因为我们是排好序的,所以相同的数就在数本身的前后,我们只需要判断当前的数是否和前面的那个数相等就好了,相等我们就跳过,避免重复。

        //除去相同的整数
        if(i > 0 && nums[i] == nums[i-1]){
            continue;
        }

        经过两轮排查之后,我们终于固定下来了第一个数,剩下的两个数我们就要从第一个数后面开始找了。定义左右两个指针,左指针从第一个数旁边开始向后走,右指针从数组的末端向前走,一个在可选范围内最小,一个在可选范围内最大。然后两个指针尝试靠拢,每一次移动,都计算一下三数之和是否为0。

        //左右指针相互靠拢
        int left = i+1;
        int right = nums.length - 1;

        如果三数之和大于0,说明加多了,右指针所指的数较大,要将右指针往左移,减小一点;如果三数之和小于0,说明加少了,左指针所指的数较小,要将左指针往右移;如果三数之和等于0,那么就将这是哪个数存入一开始定义的List集合中。

            //计算当前的三数之和
            int sum = nums[i] + nums[left] + nums[right];
            if(sum > 0){
                //sum > 0,说明加多了,右指针要往左移
                right--;
                continue;
            }else if(sum < 0){
                //sum < 0 ,说明加少了,左指针要往右移
                left++;
                continue;
            }
            //若走到这一步,说明三数之和为0
            List<Integer> data = new ArrayList();
            data.add(nums[i]);
            data.add(nums[left]);
            data.add(nums[right]);
            result.add(data);

        找到一组三数之和后,不要着急着找第二组,因为题目要求不能有重复的三元组,所以我们还要将左右指针旁边与它们相同的数先跳过之后,再找下一组。


            //跳过与左指针相同的整数
            while(left < right && nums[left] == nums[left + 1]){
                left++;
            }
            //跳过与右指针相同的整数
            while(left < right && nums[right] == nums[right- 1]){
                right--;
            }

        让左右指针不断靠拢,直到左右指针相遇,找到我们所固定的第一个数的所有可能。

            //左右指针继续靠拢
            left++;
            right--;

        之后重复上述操作,再重新固定一个新的数,左右指针继续移动找到将所有的数遍历完或者遇到第一个数大于0的情况退出循环,我们就找到了我们想要的所有结果。

3.代码展示

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;i++){
        //第一个数就大于0,那三个数不可能加起来和为0
        if(nums[i] > 0){
            break;
        }
        //除去相同的整数
        if(i > 0 && nums[i] == nums[i-1]){
            continue;
        }
        //左右指针相互靠拢
        int left = i+1;
        int right = nums.length - 1;
        while(left < right){
            //计算当前的三数之和
            int sum = nums[i] + nums[left] + nums[right];
            if(sum > 0){
                //sum > 0,说明加多了,右指针要往左移
                right--;
                continue;
            }else if(sum < 0){
                //sum < 0 ,说明加少了,左指针要往右移
                left++;
                continue;
            }
            //若走到这一步,说明三数之和为0
            List<Integer> data = new ArrayList();
            data.add(nums[i]);
            data.add(nums[left]);
            data.add(nums[right]);
            result.add(data);
            //跳过与左指针相同的整数
            while(left < right && nums[left] == nums[left + 1]){
                left++;
            }
            //跳过与右指针相同的整数
            while(left < right && nums[right] == nums[right- 1]){
                right--;
            }
            //左右指针继续靠拢
            left++;
            right--;
        }
    }
     return result;
    }
}

4.总结

        我觉得这道题的难点就在于能不能想到将数组进行排序和把一个数固定下来,将三数之和简化为两数之和。一旦想到之后,采用左右指针获取所有结果这些操作都不难想到了。同时还要记得要跳过那些相同的整数。好了,这道题就bb到这了,祝大家刷题愉快~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2231860.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

51c自动驾驶~合集4

我自己的原文哦~ https://blog.51cto.com/whaosoft/12413878 #MCTrack 迈驰&旷视最新MCTrack&#xff1a;KITTI/nuScenes/Waymo三榜单SOTA paper&#xff1a;MCTrack: A Unified 3D Multi-Object Tracking Framework for Autonomous Driving code&#xff1a;https://gi…

STM32HAL-最简单的长、短、多击按键框架(多按键)

概述 本文章使用最简单的写法实现长、短、多击按键框架,非常适合移植各类型单片机,特别是资源少的芯片上。接下来将在stm32单片机上实现,只需占用1个定时器作为时钟扫描按键即可。 一、开发环境 1、硬件平台 STM32F401CEU6 内部Flash : 512Kbytes,SARM …

【论文精读】LPT: Long-tailed prompt tuning for image classification

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;论文精读_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 摘要 2. …

队列的模拟实现

概念&#xff1a; 队列 &#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出 FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为 队尾&#xff08; Tail/Rear &#xff09; 出队列&a…

Centos安装配置Jenkins

下载安装 注意&#xff1a;推荐的LTS版本对部分插件不适配&#xff0c;直接用最新的版本&#xff0c;jenkins还需要用到git和maven&#xff0c;服务器上已经安装&#xff0c;可查看参考文档[1]、[2]&#xff0c;本次不再演示 访问开始使用 Jenkins 下载jenkins 上传至服务器…

在Python中最小化预测函数的参数

在 Python 中&#xff0c;最小化预测函数的参数通常涉及使用优化算法来调整模型的参数&#xff0c;以减少预测误差。下面介绍几种常见的方法来实现这一目标&#xff0c;主要使用 scipy 和 numpy 库。 1、问题背景 我正在尝试通过解决自己想出的问题来学习Python&#xff0c;我…

统信UOS系统应用开发

包括cpu 、内存 、安全等接口描述。 文章目录 一、内存管理非文件形式的内存动态函数库调用接口二、cpu内置安全飞腾国密加速硬件用户态驱动API说明真随机数真随机数三、cpu多核调度cpu亲和性获取接口用于cpu set集操作的相关宏定义一、内存管理 非文件形式的内存动态函数库调…

postman 获取登录接口中的返回token并设置为环境变量的方法 postman script

postman是一个比较方便的API开发调试工具&#xff0c; 我们在访问API时一般都需要设置一个token来对服务进行认证&#xff0c; 这个token一般都是通过登录接口来获取。 这个postman脚本放到登录接口的sctipt--> post-response里面即可将登陆接口中返回的token值设置到postma…

《华为工作法》读书摘记

无论做什么事情&#xff0c;首先要明确的就是做事的目标。目标是引导行动的关键&#xff0c;也是证明行动所具备的价值的前提&#xff0c;所以目标管理成了企业与个人管理的重要组成部分。 很多时候&#xff0c;勤奋、努力并不意味着就一定能把工作做好&#xff0c;也并不意味…

【大语言模型】ACL2024论文-07 BitDistiller: 释放亚4比特大型语言模型的潜力通过自蒸馏

【大语言模型】ACL2024论文-07 BitDistiller: 释放亚4比特大型语言模型的潜力通过自蒸馏 目录 文章目录 【大语言模型】ACL2024论文-07 BitDistiller: 释放亚4比特大型语言模型的潜力通过自蒸馏目录摘要研究背景问题与挑战如何解决创新点算法模型实验效果代码推荐阅读指数&…

Tomcat 和 Docker部署Java项目的区别

在 Java 项目部署中&#xff0c;Tomcat 和 Docker 是两种常见的选择。虽然它们都可以用来运行 Java 应用&#xff0c;但它们在定位、部署方式、依赖环境、资源隔离、扩展性和适用场景等方面有显著区别。 1. 功能定位 1.1 Tomcat Apache Tomcat 是一种轻量级的 Java 应用服务器…

基于SSM的学生选课系统+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

Java I/O流详解

文章目录 I/O流概念I/O流的分类字节流&#xff08;Byte Streams&#xff09;字节字节流概述方法主要类和继承关系示例代码字节流读取文件 字符流字符流概述子类Reader1.FileReader&#xff1a;2.CharArrayReader&#xff1a;3.StringReader&#xff1a;4.InputStreamReader&…

基于Multisim数字频率计频率范围0-9999HZ电路(含仿真和报告)

【全套资料.zip】数字频率计仿真电路设计Multisim仿真设计数字电子技术 文章目录 功能一、Multisim仿真源文件二、原理文档报告资料下载【Multisim仿真报告讲解视频.zip】 功能 1.采用纯数字电路&#xff0c;非单片机。 2.频率计测量的频率范围0-9999HZ。 3.使用数码管进行频…

Python画笔案例-095 绘制鼠标画笔

1、绘制 鼠标画笔 通过 python 的turtle 库绘制 鼠标画笔,如下图: 2、实现代码 绘制 鼠标画笔,以下为实现代码: """鼠标画笔.py本程序可以用鼠标指针在屏幕上画画儿。 """ import turtlescreen = turtle.getscreen() screen.setup(

【温酒笔记】SPI

1. SPI基础 物理层 片选线 &#xff1a;选中拉低SCK: 时钟线MOSI:主出从入MISO:主入从出 协议层 CPOL:时钟极性&#xff1a;空闲电平高低 CPHA:时钟相位&#xff1a;第一个还是第二个边沿采样 2. 示例SPI-W25Q16 (见模组分类下文章)

mac电脑设置crontab定时任务,以及遇到的问题解决办法

crontab常用命令 crontab -u user&#xff1a;用来设定某个用户的crontab服务&#xff1b; crontab file&#xff1a;file是命令文件的名字,表示将file做为crontab的任务列表文件并载入crontab。如果在命令行中没有指定这个文件&#xff0c;crontab命令将接受标准输入&#xf…

MySQL中,如何定位慢查询?定位到的慢SQL如何分析?

目录 1. 慢查询发生的场景&#xff1f; 2. MySQL中&#xff0c;如何定位慢查询&#xff1f; 2.1 详细解释 3. 定位到的慢SQL如何分析&#xff1f; 3.1 详细说明 1. 慢查询发生的场景&#xff1f; 2. MySQL中&#xff0c;如何定位慢查询&#xff1f; 介绍一下当时产生问题…

大数据新视界 -- 大数据大厂之提升 Impala 查询效率:索引优化的秘籍大揭秘(上)(3/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Nico,从零开始干掉Appium,移动端自动化测试框架实现

开头先让我碎碎念一波~去年差不多时间发布了一篇《 UiAutomator Nico&#xff0c;一个基于纯 adb 命令实现的安卓自动化测试框》&#xff08;https://testerhome.com/topics/37042&#xff09;&#xff0c; 由于种种原因 (详见此篇帖子) 当时选择了用纯 adb 命令来实现安卓自动…