双指针(简化哈希)力扣15.三数之和

题目

给你一个整数数组 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
  • -10^5 <= nums[i] <= 10^5

思路 

本题与四数之和Ⅱ的区别在于,本题得到的结果需要去重,如果用哈希法,去重将会十分困难并且很难做到bug free,因此我们采用双指针法来进行简化的去重和结果的实现,详细的去重细节请看下面的代码所描述的,认真观察和思考去重,是本题的一大重点。

代码实现

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {vector<vector<int>>result;//用于存储结果int i,left,right;sort(nums.begin(),nums.end());//对数组进行排序,好处有两个//1.方便我们使用双指针不断移动,向中间靠拢 2.如果发现第一位是大于0的数那么就及时终止for(i=0;i<nums.size();i++){if(nums[i]>0)return result;//如果发现i也就是第一位大于0//后面加和也一定不可能等于0,故及时终止if(i>0&&nums[i]==nums[i-1])//对第一位进行去重,这里一定要是后一位和前一位相比//因为如果前一位和后一位相比的话会导致重复元素无法计数,后一位比前一位,这样可以//刚好越过重复元素,避免-1 -1 2情况continue;left=i+1;//设置初始第二个值,也就是双指针左端right=nums.size()-1;//设置初始第三个值,也就是双指针右端while(left<right){//因为如果双指针相等,那么就重复了同一个数字,不能让其相等if(nums[i]+nums[left]+nums[right]<0)left++;//如果和小于0,那么说明和过小,让左端向右移动,也就是变大else if(nums[i]+nums[left]+nums[right]>0)right--;//如果和大于0,那么说明和过大,让右端向左移动,也就是变小//这样做刚好可以遍历所有值else{result.push_back(vector<int>{nums[i],nums[left],nums[right]});//如果发现所需值,就让其插入结果集while(left<right&&nums[left+1]==nums[left])left++;//对第二个数进行去重,如果一直相等一直右移while(left<right&&nums[right]==nums[right-1])right--;//对第三个数进行去重,如果一直相等一直左移//如果该去重放在一开始,那么0 0 0 情况就会被省略,因此我们至少找到一组再去重left++;right--;//找到一组就相对收缩一次,和前面的去重不矛盾,因为去重一直去的是相同值};}}return result;//返回结果集}
};

关键点:去重

①对第一个数去重

if(i>0&&nums[i]==nums[i-1])//对第一位进行去重,这里一定要是后一位和前一位相比//因为如果前一位和后一位相比的话会导致重复元素无法计数,后一位比前一位,这样可以//刚好越过重复元素,避免-1 -1 2情况continue;

②对第二个数去重

while(left<right&&nums[left+1]==nums[left])left++;//对第二个数进行去重,如果一直相等一直右移

③对第三个数去重

 while(left<right&&nums[right]==nums[right-1])right--;//对第三个数进行去重,如果一直相等一直左移

④去重位置和逻辑

1.对于第一个数的去重,我们要考虑是后一位和前一位相比进行去重,否则会导致,结果集缺失存在相同元素,类似于-1 -1 2的结果集。

2.对于第二第三个数的去重,我们要考虑的是去重的位置,如果过于提前,那么可能导致结果集缺失或者为空的结果集,类似于0 0 0的结果集。

总结

这道题简化了哈希算法,采用了双指针,虽然时间复杂度也不低,但是为我们提供了新的思路和思考,对bug free降低了要求,做好本题主要在于对关键点的把握和关注,如果把握好了去重的逻辑和位置,以及去重的细节和理解,那么相信做对这道题对你来说就是易如反掌。

尾声

本题通过复杂的去重和剪枝,告诉我们哈希算法的不利情况和相应的代替算法,希望大家通过本题对双指针和哈希表的认识和理解进一步加深,如果觉得笔者写的还不错的话,记得留下您的点赞,关注和收藏,和作者一起学习算法呀~

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux Capabilities 进阶实战

目录 1. 快速回顾 2. 为可执行文件分配 capabilities 3. 构建半特权环境 4. 容器与 capabilities Linux Capabilities 基础概念与基本使用 上一篇学习了LinuxCapabilities的基础知识和基本使用&#xff0c;因为后面需要学习Docker的逃逸&#xff0c;理解Linux Capabilitie…

网工内推 | 运维工程师,国企、上市公司,RHCE认证优先

01 广东机场白云信息科技股份有限公司 招聘岗位&#xff1a;基础架构运维工程师&#xff08;中级&#xff09; 职责描述&#xff1a; 1、参与公司业务系统的监控、巡检、维护、故障定位、原因分析&#xff1b; 2、负责业务系统的上线、升级割接工作&#xff1b; 3、负责服务器…

作业--day43

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数&#xff0c;将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c…

python 基础笔记

基本数据类型 函数 lamda 匿名函数 成员方法 类 类与对象 构造方法 魔术方法 私有成员 私有方法 继承 注解 变量注解 函数注解 Union类型 多态 参考链接&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了_哔哩哔哩_bilib…

Java中的网络编程

文章目录 网络基础知识IP 地址端口协议 Java 中网络编程InetAddress&#xff08;静态类&#xff09;UDP 通信原理UDP 发送数据步骤UDP 接收数据步骤UDP 发送接收案例 TCP 通信原理TCP 发送数据步骤TCP 接收数据步骤TCP 发送接收案例 网络基础知识 概述&#xff1a;在网络通信协…

vue3 +TS 安装使用router路由模块

一.安装 1.下载安装依赖 npm install vue-routernextnpm install types/vue-router2.router目录创建 在src 目录下 创建 /src/router文件夹 包含两个文件 route.ts import { RouteRecordRaw } from vue-routerconst routes: Array<RouteRecordRaw> [{path: /,name:…

尚硅谷大数据技术-数据湖Hudi视频教程-笔记01【概述、编译安装】

大数据新风口&#xff1a;Hudi数据湖&#xff08;尚硅谷&Apache Hudi联合出品&#xff09; B站直达&#xff1a;https://www.bilibili.com/video/BV1ue4y1i7na 尚硅谷数据湖Hudi视频教程百度网盘&#xff1a;https://pan.baidu.com/s/1NkPku5Pp-l0gfgoo63hR-Q?pwdyyds阿里…

Kubernetes复习总结(二):Kubernetes容器网络

2、Kubernetes容器网络 1&#xff09;、Docker网络原理 Docker默认使用的网络模型是bridge&#xff0c;这里只讲bridge网络模型 1&#xff09;容器之间通信原理 当安装完docker之后&#xff0c;docker会在宿主机上创建一个名叫docker0的网桥&#xff0c;默认IP是172.17.0.1…

Tensorflow2.0笔记 - 创建tensor

tensor创建可以基于numpy&#xff0c;list或者tensorflow本身的API。 笔记直接上代码&#xff1a; import tensorflow as tf import numpy as np import matplotlib.pyplot as plttf.__version__#通过numpy创建tensor tensor0 tf.convert_to_tensor(np.ones([2,3])) print(te…

Java程序员面试-场景篇

前言 裁员增效潮滚滚而来&#xff0c;特总结一些实际场景方案的面试题&#xff0c;希望对大家找工作有一些帮助。 注册中心 题目&#xff1a; 有三台机器&#xff0c;分别部署了微服务A、微服务B、注册中心&#xff0c;其中A和B都有服务接口提供并正常注册到了注册中心&…

H264/AVC的句法和语义

概述 码流的基本单位&#xff1a; 在编码器输出的码流中&#xff0c;数据的基本单位是句法元素&#xff0c;每个句法元素由若干比特组成&#xff0c;它表示某个特定的物理意义 &#xff0c;比如宏块类型、量化参数等。 句法&#xff1a;句法表征句法元素的组织结构。 语义&a…

【Spring Cloud】Gateway组件的三种使用方式

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《Spring Cloud》。&#x1f3af;&#x1f3af; &am…