Leetcode:三数之和

题目链接:15. 三数之和 - 力扣(LeetCode)

普通版本(排序 + 双指针法)

分析:

1、我们可以通过三个循环嵌套找到符合题目要求的三元组组合

2、但由于题目要求中的三元组i、j、k并不要求连续,所以会出现下面的情况:

3、因此直接对原数组进行查找,可能会出现重复的情况,比如有abc的组合均满足条件但该组合有多种表现形式(a,c,b)(b,c,a)等重复的组合会导致我们的查找效率大大下降,因此我们应该先将数组进行排序,使得查找时三元组的顺序必然是从到大排序的,从而减少查找次数增加查找效率(假设排序前abc的组合满足要求,且a<=b<=c,那么排序后再进行查找时就不会出现(b,c,a)这种组合,最小的a一定是在最左边的)

sort(nums.begin(), nums.end());//排序

4、但是这样还不够,在循环时,相邻两次查找到的数组也不能相同否则也是重复,我们要跳转至下一个元素处,应该去查找组合(0,1,3):

//实现上述防止重复查找的逻辑伪代码:
nums.sort()
for(first = 0 .. n-1)
{// 只有和上一次枚举的元素不相同,我们才会进行枚举if (first == 0 or nums[first] != nums[first-1]){for(second = first+1 .. n-1){if (second == first+1 or nums[second] != nums[second-1]){for(third = second+1 .. n-1){if(third == second+1 or nums[third] != nums[third-1]){// 判断是否有 a+b+c==0check(first, second, third)}}}}}
}                   

5、此时每次查找时一定满足,a<a‘、b<b'、c<c’(带'的都是新一次查找的),但最坏时间复杂度仍为O(N^3),我们尝试继续优化,我们会发现如果我们固定了前两重循环枚举到的元素 a 和 b,那么只有唯一的 c 满足 a+b+c=0,当第二重循环往后查找一个元素 b′时,由于 b′>b ,那么满足 a+b′+c′=0的 c′ 一定有 c′<c 即 c′ 在数组中一定出现在 c 的左侧。也就是说,我们可以从小到大枚举 b,同时从大到小枚举 c,即第二重循环和第三重循环实际上是并列的关系。有了这样的发现,我们就可以保持第二重循环不变,而将第三重循环变成一个从数组最右端开始向左移动的指针,从而得到下面的伪代码:

nums.sort()//排序
for (first = 0 .. n-1)    
{if(first == 0 or nums[first] != nums[first-1]){third = n-1;// 第三重循环对应的指针for(second = first+1 .. n-1){if(second == first+1 or nums[second] != nums[second-1]){// 向左移动指针,直到 a+b+c 不大于 0while(nums[first]+nums[second]+nums[third] > 0){third = third-1;}// 判断是否有 a+b+c==0check(first, second, third)}    }}
}
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {int n = nums.size();sort(nums.begin(), nums.end());//排序vector<vector<int>> ans;// 枚举 afor (int first = 0; first < n; ++first) {// 需要和上一次枚举的数不相同if (first > 0 && nums[first] == nums[first - 1]) //first>0保证第一次循环可以正常进行,但是当第二次循环时如果两个a相同就,++first寻找下一个不相同的a{continue;}// c 对应的指针初始指向数组的最右端int third = n - 1;//int target = -nums[first];//获取a的负值,a+b+c = 0 => b + c = (-a)// 枚举 bfor (int second = first + 1; second < n; ++second) {// 需要和上一次枚举的数不相同if (second > first + 1 && nums[second] == nums[second - 1])//跟前面一样,首先第一次循环要可以正常进行{continue;}// 需要保证 b 的指针在 c 的指针的左侧while(second < third && nums[first]+nums[second]+nums[third] > 0){--third;}// 如果指针重合,随着 b 后续的增加,就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环if (second == third) {break;}if (nums[first]+nums[second]+nums[third] == 0) {ans.push_back({nums[first], nums[second], nums[third]});}}}return ans;}
};

时间复杂度:O(N^2)

空间复杂度:O(logN)(忽略存储答案的空间,额外的排序的空间复杂度为 O(log⁡N))

~over~

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

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

相关文章

【Tools】 探索 Chrome DevTools:前端开发者的必备工具

我已经从你的 全世界路过 像一颗流星 划过命运 的天空 很多话忍住了 不能说出口 珍藏在 我的心中 只留下一些回忆 &#x1f3b5; 牛奶咖啡《从你的全世界路过》 在现代Web开发中&#xff0c;Chrome DevTools&#xff08;开发者工具&#xff09;是前端开发…

彩虹易支付最新版源码

源码简介 彩虹易支付最新版源码&#xff0c;更新时间为5.1号 2024/05/01&#xff1a; 1.更换全新的手机版支付页面风格 2.聚合收款码支持填写备注 3.后台支付统计新增利润、代付统计 4.删除结算记录支持直接退回商户金额 安装环境 1.PHP版本>7.4 2.Mysql数据库 安装教…

Leetcode:电话号码的字母组合

题目链接&#xff1a;17. 电话号码的字母组合 - 力扣&#xff08;LeetCode&#xff09; 普通版本&#xff08;回溯&#xff09; class Solution { public:string tmp;//临时存放尾插内容vector<string> res;//将尾插好的字符串成组尾插给resvector<string> board{…

【小沐学Python】Python实现Web服务器(CentOS下打包Flask)

文章目录 1、简介2、下载Python3、编译Python4、安装PyInstaller5、打包PyInstaller6、相关问题6.1 ImportError: urllib3 v2 only supports OpenSSL 1.1.1, currently the ssl module is compiled with OpenSSL 1.0.2k-fips 26 Jan 2017. See: https://github.com/urllib3/url…

Linux系统管理:虚拟机Almalinux 9.4 安装

目录 一、理论 1.Almalinux 二、实验 1.虚拟机Almalinux 9.4 安装准备阶段 2.安装Almalinux 9.4 3.Termius远程连接 一、理论 1.Almalinux (1) 简介 Almalinux是一个开源、社区拥有和管理、免费的企业Linux发行版。专注于长期稳定性&#xff0c;并提供强大的生产级…

1025 反转链表

solution 模拟链表&#xff1a;记录链表中第i个元素的地址&#xff0c;再记录每个给定地址的对应数据和下一结点地址。注意给出的结点可能有的无效 #include<iostream> #include<algorithm> using namespace std; const int maxn 1e5 10; int main(){int n, k,…

Nginx(title小图标)修改方法

本章主要讲述Nginx如何上传网站图标。 操作系统&#xff1a; CentOS Stream 9 首先我们bing搜索ico网站图标在线设计&#xff0c;找到喜欢的设计分格并下载。 是一个压缩包 然后我们上传到nginx解压 [rootlocalhost html]# rz[rootlocalhost html]# unzip favicon_logosc.z…

【AI大模型】Prompt Engineering

目录 什么是提示工程&#xff08;Prompt Engineering&#xff09; Prompt 调优 Prompt 的典型构成 「定义角色」为什么有效&#xff1f; 防止 Prompt 攻击 攻击方式 1&#xff1a;著名的「奶奶漏洞」 攻击方式 2&#xff1a;Prompt 注入 防范措施 1&#xff1a;Prompt 注…

请求 响应

在web的前后端分离开发过程中&#xff0c;前端发送请求给后端&#xff0c;后端接收请求&#xff0c;响应数据给前端 请求 前端发送数据进行请求 简单参数 原始方式 在原始的web程序中&#xff0c;获取请求参数&#xff0c;需要通过HttpServletRequest 对象手动获取。 代码…

Thinkphp5实现自定义路由和使用方法

在 ThinkPHP 5 中&#xff0c;实现自定义路由方法通常涉及到定义路由规则和对应的处理逻辑。虽然 ThinkPHP 5 的路由系统已经相当强大和灵活&#xff0c;但如果你需要实现自定义的路由方法&#xff0c;你可能需要扩展或修改现有的路由解析机制。 不过&#xff0c;对于大多数情…

SpringBoot——整合WebSocket长连接

目录 WebSocket 项目总结 新建一个SpringBoot项目 pom.xml WebSocketConfig配置类 TestWebSocketEndpoint服务端点类 socket.html客户端 IndexController控制器 SpringbootWebsocketApplication启动类 测试客户端和服务端如何使用WebSocket进行连接和通信 WebSocket S…

vscode 突然无法启动 WSL terminal 了怎么办?

参考&#xff1a;https://github.com/microsoft/vscode/issues/107485 根据参考网页&#xff0c;似乎在 windows 更新之后&#xff0c;重启&#xff0c;就有可能出现标题所说的 vscode 无法启动 WSL terminal 的情况。 首先使用 cmd 进入 wsl 终端&#xff0c;把 ~/.vscode-se…

(八)Mybatis持久化框架原理之不同Executor对比和Spring事务关系

文章目录 1. SqlSession的差异2. Executor的差异2.1 SimpleExecutor流程说明2.2 ReuseExecutor流程说明2.3 BatchExecutor流程说明 3. Mybatis事务4. Spring事务5. 总结 本篇文章主要是由一次批量插入数据而引起的思考与探究&#xff0c;在这篇文章中将会分析不同的Executor和S…

Vue3+springboot+sa-token

sa-token是什么? sa-token官网Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。 springboot前后端分离集成sa-token maven <!-- Sa-Token 权限认证,在线文档:…

快来速领限量免费亚马逊云科技助理级架构师(SAA)和云从业者50%半价考试券

前几天在上海5/29的亚马逊云科技Summit峰会里&#xff0c;小李哥在现场分享了AWS 13张认证大满贯的心得&#xff08;图1&#xff09;&#xff0c;并且现场招募了自己的云师兄必过班(图2)。 本次必过班也为成员发放AWS SAA(助理级架构师)和云从业者(Cloud Practitioner)50%考试券…

面向对象程序设计

class是关键字&#xff0c;表示要定义类了 类的属性&#xff0c;即定义在类中的变量&#xff08;成员变量&#xff09; 类的行为&#xff0c;即定义在类中的函数&#xff08;成员方法&#xff09; self关键字是成员方法定义的时候&#xff0c;必须填写的。 它用来表示类对象…

AIGC作答《2024年高考作文|新课标I卷》能拿多少分?

AIGC作答《2024年高考作文&#xff5c;新课标I卷》能拿多少分&#xff1f; 一、前言二、题目三、作答 一、前言 如火如荼的2024年高考圆满落幕&#xff0c;在如此Happy的时刻&#xff0c;AIGC技术正以其前所未有的热度席卷全球。它不仅改变了我们获取信息的方式&#xff0c;也…

Rust-10-数据类型

Rust 标准库中包含一系列被称为 集合&#xff08;collections&#xff09;的非常有用的数据结构。大部分其他数据类型都代表一个特定的值&#xff0c;不过集合可以包含多个值。不同于内建的数组和元组类型&#xff0c;这些集合指向的数据是储存在堆上的&#xff0c;这意味着数据…

【risc-v】arm和riscv有什么关系或者联系?

ARM和RISC-V都是基于精简指令集计算&#xff08;RISC&#xff09;原理的处理器架构&#xff0c;它们在设计理念上有一定的联系&#xff0c;但同时存在一些关键的区别&#xff1a; 设计理念&#xff1a;ARM和RISC-V都采用了RISC的核心设计原则&#xff0c;即通过简化指令集来提高…

C++知识点总结(36):深度优先搜索算法

DFS 一、概念二、典型题目1. 题目2. 分析3. 参考答案 三、变形题目1. 路径数量1.1 审题1.2 思路 2. 走迷宫的过程2.1 审题2.2 参考答案 一、概念 深度优先搜索&#xff08;简称 DFS&#xff09;&#xff0c;其工作原理为不撞南墙不回头&#xff0c;能深则深&#xff0c;不能则退…