当前位置: 首页 > news >正文

双指针-15.三数之和-力扣(LeetCode)

一、题目解析

1.不重复

结合示例1,我们能知道[-1,0,1]和[0,1,-1]是相同的三元组,因为他们包含相同的元素。

2.顺序不重要

同样结合示例1 ,输出顺序不重要是指在输出结果时,不关心三元组的顺序;三元组顺序是指三元组内元素排列顺序不重要,例[-1,0,1],也可以是[0,-1,1]、[0,1,-1]等等

二、算法原理

解法1:排序+暴力枚举+set去重 时间复杂度为0(N^3)

毫无疑问这是暴力解法,但我们需要了解暴力解法,便于我们在暴力解法的基础上优化。

解法2:排序+双指针+set去重 时间复杂度为0(N^2)

1.先对数组进行排序

2.固定nums[i],当nums[i]>0,找不到满足的三元组 (排序过后,nums[i]以后都是正数,无法找到负数,使其和为0)

3.在该数后面的区间内,利用“双指针算法”,快速找到两个和为-nums[i]

解法3:排序+双指针+不用set去重 时间复杂度为O(N^2)

为了避免面试时遇到该问题,面试官不允许使用set去重,故多一种解法

1.在双指针区间内找到一种结果之后,left和right指针越过重复元素

2.当使用完一次双指针算法之后,i也需要越过重复元素

细节问题

1.如何保证不漏

在双指针区间内找到一种结果后,不要停,缩小区间继续寻找

2.避免越界问题

在越过重复元素时,需注意越界问题

可以先尝试解法2,然后再去试试解法3,提升自己的代码能力

三、代码示例

解法2:

vector<vector<int>> threeSum(vector<int>& nums){set<vector<int>> s;//set具有去重的性质vector<vector<int>> vv;sort(nums.begin(),nums.end());//排序if(nums[0] == 0 && nums[nums.size()-1] == 0){vv.push_back({0,0,0});//这里会自己转化为vector<int>return vv;}int i = 0,a = 0;int left = 0,right = 0;for(;i<nums.size();i++){a = nums[i];if(a>0) break;//当a<=0时,才存在三元组left = i+1;right = nums.size()-1;if(left>right) break;while(left < right){if(nums[left]+nums[right] < -a) left++;else if(nums[left]+nums[right] > -a) right--;else{s.insert({nums[i],nums[left],nums[right]});left++;right--;}}}for(auto e : s)//范围for,从s中依次取出元素{vv.push_back(e);}return vv;}

 

解法3:

vector<vector<int>> threeSum(vector<int>& nums){vector<vector<int>> ret;sort(nums.begin(),nums.end());int n = nums.size();for(int i = 0;i<n;){if(nums[i]>0) break;int left = i+1,right = n-1,target = -nums[i];while(left<right){int sum = nums[left]+nums[right];if(sum>target) right--;else if (sum<target) left++;else{ret.push_back({nums[i],nums[left],nums[right]});left++,right--;//去重操作while(left<right && nums[left] == nums[left-1]) left++;while(left<right && nums[right] == nums[right+1]) right--;}}//去重ii++;//这里代替for循环++功能,所以for循环处为空while(i < n && nums[i] == nums[i-1]) i++;}return ret;}

 

 可以看的出来,解法2最方便,但时间和空间上都比不过解法3,但解法3需要注意数组越界问题,所以在理解的基础上掌握解法3,无疑是最优选择

看到最后,如果对您有所帮助,还请点赞、关注和收藏,我们下期再见!

http://www.xdnf.cn/news/1090783.html

相关文章:

  • 算法核心知识复习:排序算法对比 + 递归与递推深度解析(根据GESP四级题目总结)
  • Oracle 数据库升级踩坑:DBLink ORA-02019 问题解决思路
  • 使用 Docker 搭建 Rust Web 应用开发环境——AI教你学Docker
  • 工程改Mvvm
  • 一天一道Sql题(day04)
  • 基于lottie的微信小程序动画开发指南
  • CSS中的Element语法
  • 仓颉语言 1.0.0 升级指南:工具链适配、collection 操作重构与 Map 遍历删除避坑
  • ali linux 安装libreoffice
  • 《重构项目》基于Apollo架构设计的项目重构方案(多种地图、多阶段、多任务、状态机管理)
  • Context Engineering:从Prompt Engineering到上下文工程的演进
  • Ragas的Prompt Object
  • 微软 Bluetooth LE Explorer 实用工具的详细使用分析
  • JVM字节码加载与存储中的细节
  • 川翔云电脑:突破硬件极限,重构设计生产力范式
  • 【vim中替换】
  • 【自动驾驶】经典LSS算法解析——深度估计
  • BEV感知算法:自动驾驶的“上帝视角“革命
  • django 一个表中包括id和parentid,如何通过parentid找到全部父爷id
  • 免费扫描软件NAPS2:跨平台支持 旋转裁剪 + 多页合并,纸质文档变 PDF / 图片
  • 详解Kafka重平衡机制详解
  • Python(30)基于itertools生成器的量子计算模拟技术深度解析
  • 18-C#改变形参内容
  • 《设计模式之禅》笔记摘录 - 5.代理模式
  • AI应用实践:制作一个支持超长计算公式的计算器,计算内容只包含加减乘除算法,保存在一个HTML文件中
  • 设计模式(行为型)-责任链模式
  • Flink Forward Asia 2025 主旨演讲精彩回顾
  • 两张图片对比clip功能
  • React 19 概览:新特性与生态系统变革
  • 1.1 ARMv8/ARMv9安全扩展