专题1 - 双指针 - leetcode 15. 三数之和 - 中等难度

news2024/10/22 22:52:29

leetcode 15. 三数之和 - 点击直达

  • leetcode 15. 三数之和 中等难度 双指针
    • 1. 题目详情
      • 1. 原题链接
      • 2. 基础框架
    • 2. 解题思路
      • 1. 题目分析
      • 2. 算法原理
      • 3. 时间复杂度
    • 3. 代码实现
    • 4. 知识与收获

在这里插入图片描述

leetcode 15. 三数之和 中等难度 双指针

1. 题目详情

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != 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

1. 原题链接

leetcode 15. 三数之和

2. 基础框架

● Cpp代码框架

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        
    }
};

2. 解题思路

1. 题目分析

( 1 ) (1) (1) 本题要求找出数组 n u m s nums nums中满足条件:三个位置都不同数 n u m s [ i ] + n u m s [ j ] + n u m s [ k ] = = t a r g e t nums[i]+nums[j]+nums[k]==target nums[i]+nums[j]+nums[k]==target的所有结果。

2. 算法原理

( 1 ) (1) (1) 首先想到暴力解法:先进行三层for循环遍历数组 n u m s nums nums,然后使用C++中set容器对结果进行去重处理,时间复杂度是 O ( n 3 ) O(n^3) O(n3)

( 2 ) (2) (2) 在分析三数之和之前,我们先来看看两数之和为target时,如何在nums中寻找这两个数:
首先还是想到暴力解法:进行两层for循环,时间复杂度 O ( n 2 ) O(n^2) O(n2),如何优化呢?

使用对撞双指针算法:
先看张图吧:
在这里插入图片描述

先对数组 n u m s nums nums进行快速排序, n u m s nums nums中就得到非递减的序列;
有序数组好就好在有序上,我们就可以找规律了:
左指针left指向第一个元素,右指针right指向最后一个元素。此时两个数的和 s u m = n u m s [ l e f t ] + n u m s [ r i g h t ] sum = nums[left] + nums[right] sum=nums[left]+nums[right] 注意这是一个有序数组,left指向的元素是[left, right]范围内最小的元素,right指向的元素是[left, right]中最大的元素。
sum的变化情况是:left向右移动时,sum不变或增大;right向左移动时sum不变或减小;
所以我们可以通过比较sumtarget(本题target是0)的大小来确定移动的情况:
1.sum > target,想要趋近targetsum需要减小,所以移动右指针right
2.sum < target,想要趋近targetsum需要增大,所以移动左指针left
3.sum == target,得到了一个结果nums[left]和nums[right]。但是题目要求得到所有的结果,所以还需要继续,此时为了保证结果不重复,需要依据当前得到的结果进行去重处理(即当前已经有了结果nums[left],之后的出现的所有与nums[left]相同的元素都直接略过不在考虑,因为一定是结果中有的。right同理)
本题去重就是控制left和right跳过所有与自身重复的元素,这里需要注意的是控制left++或right--时需要先判断left或right是否越界,因为在极端情况下所有元素都相同,指针一直移动导致越界(细节细节)
在这里插入图片描述

( 3 ) (3) (3) 好了,现在我们来看三数之和,其实就是上文两数之和的变形。三数之和的题目要求 n u m s [ i ] + n u m s [ l e f t ] + n u m s [ r i g h t ] = = t a r g e t nums[i]+nums[left]+nums[right]==target nums[i]+nums[left]+nums[right]==target本题target为0),变形为 n u m s [ l e f t ] + n u m s [ r i g h t ] = = t a r g e t − n u m s [ k ] nums[left]+nums[right]==target-nums[k] nums[left]+nums[right]==targetnums[k],把target-nums[i]整体当做新的target,记为newtarget,所以得到 n u m s [ l e f t ] + n u m s [ r i g h t ] = = n e w t a r g e t nums[left]+nums[right] == newtarget nums[left]+nums[right]==newtarget
在这里插入图片描述

( 4 ) (4) (4) 具体做法就是在两数之和的基础上在加上一层循环,遍历数组nums,每次确定一个nums[i],即确定一个newtarget。内层双指针leftright在范围[i+1, n-1]内以newtarget为目标进行寻找。
在本次循环结束时需要额外在做的一点是对nums[i]也要进行进行去重处理,同时也需要进行是否越界访问的判断(细节细节),至于为什么要进行去重,原理和两数之和做法类似。

( 5 ) (5) (5)

3. 时间复杂度

O ( n 2 ) O(n^2) O(n2)

外层循环每次确定一个目标值,内层循环在目标值之后的区间内寻找满足两数之和条件的结果。

3. 代码实现

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> vvi;
        // 排序
        sort(nums.begin(), nums.end());
        int n = nums.size();
        for(int i = 0; i < n;){
            // 两数之和
            int l = i + 1, r = n - 1;
            while(l < r){
                int sum = nums[l] + nums[r];
                int target = -nums[i];
                if(sum > target) r--;
                else if(sum < target) l++;
                else{
                    vvi.push_back({nums[i], nums[l], nums[r]});
                    l++;
                    r--;
                    //去重
                    while(l < r && nums[l] == nums[l - 1]) l++;
                    while(l < r && nums[r] == nums[r + 1]) r--;
                } 
            }
            // 去重
            i++;
            while(i < n && nums[i] == nums[i - 1]) i++;
        }
        return vvi;
    }
};

4. 知识与收获

( 1 ) (1) (1) 三数之和是两数之和的变形,理解了两数之和的核心思想,三数之和也就能够顺理成章的解决。
( 2 ) (2) (2) 理解为什么需要去重处理:
对于两数之和(a+b=target):一个组合(a, b)满足了条件,数组又是有序的,对于a来说,以后的所有与其相同的数如果也满足了条件,那么一定会与(a,b)组合相同;对于b来说与a同理。
对于三数之和(a+b+c=target):变形为(a+b=target-c),target确定,本次循环内c也确定


T h e The The E n d End End

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

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

相关文章

SQL 替换某一列中所有数据的特定字符

UPDATE product SET spec REPLACE(spec, ,, ) 把product表的spec字段内容中的逗号替换为

性能问题分析排查思路之机器(3)

本文是性能问题分析排查思路的展开内容之一&#xff0c;第2篇&#xff0c;主要分为日志1期&#xff0c;机器4期、环境2期共7篇系列文章&#xff0c;本期是第三篇&#xff0c;讲机器&#xff08;硬件&#xff09;的网络方面的排查方法和最佳实践。 主要内容如图所示&#xff1a…

Java请求时间耗时长分析

推断是java.lang.OutOfMemoryError: Metaspace&#xff0c;元空间不够&#xff0c;频繁垃圾收集 这个过程中程序卡住一直不响应&#xff0c;应该是触发FGC有关系。 YGC&#xff1a;451->453 FGC&#xff1a;198->289 FGCT&#xff1a;52.246->76.291 但是堆内存的空间…

简易网络聊天室:2024/3/7

思维导图 基于UDP的简易网络聊天室 服务器&#xff1a; #include <myhead.h>#define SER_PORT 8888struct msgTyp //存储消息的结构体 {char type; //消息类型char name[30]; //用户姓名char text[1024]; //消息正文 };//创建链表存储客户端信息 typedef stru…

【计算机考研】考408,还是不考408性价比高?

首先综合考虑&#xff0c;如果其他科目并不是很优秀&#xff0c;需要我们花一定的时间去复习&#xff0c;408的性价比就不高&#xff0c;各个科目的时间互相挤压&#xff0c;如果备考时间不充裕&#xff0c;考虑其他专业课也未尝不可。 复习408本来就是费力不讨好的事情 不同…

SAP MM学习笔记44 - 特殊调达流程 - Blanket购买发注(汇总采购)

上一章学习了 支付计划&#xff0c;本章继续学习 Blanket购买发注&#xff08;汇总采购&#xff09;。 SAP MM学习笔记43 - 特殊调达流程 - 支付计划-CSDN博客 1&#xff0c;Blanket购买发注 概要 其实就是订好一个大致数额&#xff0c;然后让随便买&#xff0c;只要不超这个…

网络调试助手使用MQTT协议与Mosquitto通信(3)

一、连接报文 一开始设备需要连接到mqtt服务器&#xff0c;连接时的数据包内需要携带对应的设备ID&#xff0c;以及用户名和密码。这使用默认的用户名和密码。设备ID每一个设备都需要设置为不同的&#xff0c;两个相同的ID只能允许一台设备在线&#xff0c;另一个相同的ID的设备…

2024年最新阿里云服务器地域选择方法,以及可用区说明

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

实操keepalived(高可用)+Nginx(四层代理+七层代理),实现高可用、负载均衡以及动静分离

一 vrrp技术 VRRP 相关术语 VRRP能够在不改变组网的情况下&#xff0c;将多台路由器虚拟成一个虚拟路由器&#xff0c;i通过配置虚拟路由器的IP地址为默认网关&#xff0c;实现网关的备份。 协议版本: VRRPv2 (常用) 和VRRPv3:0 VRRPv2仅适用于IPv4网络&#xff0c;VRRPv3适用…

好物周刊#46:在线工具箱

https://github.com/cunyu1943 村雨遥的好物周刊&#xff0c;记录每周看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;每周五发布。 一、项目 1. twelvet 一款基于 Spring Cloud Alibaba 的权限管理系统&#xff0c;集成市面上流行库&#xff0c;可以作用为快…

数字孪生10个技术栈:数据采集的八种方式

大家好&#xff0c;我是贝格前端工场&#xff0c;上期讲了数字孪生10个技术栈&#xff08;总括&#xff09;:概念扫盲和总体介绍&#xff0c;获得了大家的热捧&#xff0c;本期继续分享技术栈&#xff0c;大家如有数字孪生或者数据可视化的需求&#xff0c;可以联络我们。 一、…

文件包含漏洞初识

一、基础知识介绍 在web后台开发的时候&#xff0c;我们会使用PHP&#xff0c;Java这种代码&#xff0c;而在使用的过程中&#xff0c;我们经常会使用包含函数&#xff08;也就是调用&#xff09;&#xff0c;而很多时候&#xff0c;前端用户在选择浏览时会调用包含的文件这无…

LangChain自定义工具Tool

LangChain部署 pip install langchain自定义工具 from langchain_openai import ChatOpenAI from langchain.memory import ConversationBufferMemory from langchain.agents.conversational_chat.base import ConversationalChatAgent from langchain.agents import AgentEx…

常见四种限流算法详解(附:javaDemo)

限流简介 现代互联网很多业务场景&#xff0c;比如秒杀、下单、查询商品详情&#xff0c;最大特点就是高并发&#xff0c;而往往我们的系统不能承受这么大的流量&#xff0c;继而产生了很多的应对措施&#xff1a;CDN、消息队列、多级缓存、异地多活。 但是无论如何优化&…

Material Studio 中 DMol3 计算材料吸附能

1.先导入Cif文件 2.切表面 3.沿着你要切的晶面切 4.扩胞 5.加真空层&#xff08;一般加10埃&#xff09; 现在就是这样的了 6.然后对其结构优化&#xff08;高斯几何优化&#xff09; 7.再在体系上加原子或者想要的材料 8.Outmal文件中最后的Ef就是整个体系的能量&#xff0…

腾讯云哪款服务器最便宜划算?2024腾讯云服务器优惠价格表

腾讯云优惠活动2024新春采购节活动上线&#xff0c;云服务器价格已经出来了&#xff0c;云服务器61元一年起&#xff0c;配置和价格基本上和上个月没什么变化&#xff0c;但是新增了8888元代金券和会员续费优惠&#xff0c;腾讯云百科txybk.com整理腾讯云最新优惠活动云服务器配…

2024第二届语言,教育与艺术鉴赏国际会议(ICLEAA 2024)

2024第二届语言&#xff0c;教育与艺术鉴赏国际会议&#xff08;ICLEAA 2024&#xff09; 一、【会议简介】 我们非常荣幸地邀请您参加2024第二届语言&#xff0c;教育与艺术鉴赏国际会议&#xff08;ICLEAA 2024&#xff09;&#xff0c;该会议将在美丽的苏州举行。 ICLEAA …

Mybatis-Plus Mapper映射文件使用

介绍 MyBatis 的真正强大在于它的语句映射&#xff0c;这是它的魔力所在。由于它的异常强大&#xff0c;映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比&#xff0c;你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本&#xff0…

一篇文章带你通关并查集(持续更新中)

这篇文章的所有题目均来自于自行整理&#xff0c;代码均来自于自行梳理调试&#xff08;思路可能比较暴力&#xff09;。初衷在于整理练习思路&#xff0c;且起到督促自己学习的作用 本文分成将三个模块 1.普及组 &#xff08;洛谷黄题&#xff09; 2.提高组 &#xff08;洛…

OracleXE112、plsqldev1207的安装和基本配置

OracleXE112、plsqldev1207的安装和基本配置 OracleXE112、plsqldev1207的安装和基本配置Oracle安装oracle是什么Oracle两个版本下载安装包 安装OracleXE112_Win64注意&#xff1a;安装到空目录下&#xff1b;输入口令&#xff08;记住啊&#xff01;&#xff09;安装成功&…