双指针算法系列:一快一慢解决两数之和、三数之和与四数之和
创作时间:
作者:
@小白创作中心
双指针算法系列:一快一慢解决两数之和、三数之和与四数之和
引用
CSDN
1.
https://m.blog.csdn.net/2303_81060385/article/details/143601155
本篇是双指针算法系列的最终篇,通过三个难度递增的题目,进一步强化对双指针算法的理解和运用。
相关题目及讲解
一. 两数之和
题目链接:LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)
题目分析:
- 该题要求较为简单,只需要在数组中查找两个和为target的元素,并将他们储存在需要返回的数组中即可。
- 需要注意找到任一一对即可返回,无需返回多种情况。
思路讲解:
解法一:暴力解法(会超时)
很容易想到采用两个for循环直接逐个遍历的方式,符合要求即可直接返回。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int n = nums.size();
for (int i = 0; i < n; i++) { // 第一层循环从前往后列举第一个数
for (int j = i + 1; j < n; j++) { // 第二层循环从 i 位置之后列举第二个数
if (nums[i] + nums[j] == target) // 两个数的和等于目标值,说明我们已经找到结果了
return {nums[i], nums[j]};
}
}
return {-1, -1};
}
};
解法二:对撞指针
基于解法一遍历思想的基础之上,我们对其通过减少遍历次数进行优化。
- 首先对数组进行排序
- 定义left=0,right=n-1,分别位于数组的左右两侧,代表最小和最大值。
- 用sum表示nums[left]与nums[right]的和,与target比较。
- 如果sum>target,则此时和过大,应该让right--
- 如果sum<target,则此时和过小,应该让left++
- 如果sum=target,插入返回的数组中直接返回即可
代码实现:
class Solution {
public:
vector<int> twoSum(vector<int>& price, int target) {
int n=price.size();
vector<int> ret;
int left=0,right=n-1;
while(left<right)
{
int sum=price[left]+price[right];
if(sum>target)
{
right--;
}
if(sum<target)
{
left++;
}
if(sum==target)
{
ret.push_back(price[left]);
ret.push_back(price[right]);
return ret;
}
}
return ret;
}
};
二. 三数之和
题目链接:15. 三数之和 - 力扣(LeetCode)
题目分析:
- 需要在一个数组内查找三个相加后和为0的元素
- 这三个元素不能重复,但元素的值可以相同
- 输出中不能包含内容相同的三元数组
思路讲解:
解法一: 暴力解法(会超时)
思路与两数之和大致相同,只是需要再嵌套一层for循环代表第三个数即可。
此时时间复杂度已经来到了恐怖的O(n^3),基本上是一定会超时的。
解法二:对撞指针
- 首先排序数组
- 在求解两数之和时,我们就采取了对撞指针的方法,那么此时是三数之和,我们只需要固定一个数,在该数右侧的区间内使用对撞指针即可。
- 使用for循环初始化一个i,那么i表示的就是我们需要固定的值,令left=i+1,right=n-1,重复两数之和的操作即可。只不过这次所求的target为-nums[i]。
- 在查找到符合条件的元素时,我们将nums[i],nums[left],nums[right]插入要返回的数组中,并进行去重操作:
- 由于每一轮插入成功后,都会令left++,right--,此时要考虑以下几种情况进行去重:
- 当nums[left]=nums[left-1]时,说明此处的left元素与上一个插入的相同,因此需要left++进行跳过。
- 当nums[right]=nums[right+1]时,说明此处的right元素与上一个插入的相同,因此需要right--进行跳过。
- 注意:循环和去重操作均需满足条件left<right!!!
- i的去重操作与上基本相同。
代码实现:
class Solution {
public:
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;)
{
int target=-nums[i];
if(target<0)
{
break;
}//说明元素全部大于0,不存在满足的情况
int left=i+1,right=n-1;
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--;
}
}
}
i++;
while(i<n&&nums[i]==nums[i-1])
{
i++;
}
}
return ret;
}
};
三. 四数之和
题目链接:18. 四数之和 - 力扣(LeetCode)
题目分析:
- 从数组内寻找4个加起来和为target的元素插入到需要返回的数组中
- 元素不可以重复
- 元素所代表的值可以重复
- 需要返回所有情况
思路讲解:
- 首先排序数组
- 基于三数之和的思想,我们只需要固定一个数,在其右侧的区间进行三数之和的对撞指针和去重操作即可。
- 需注意固定的这个数字在遍历的时候也需要去重。
代码实现:
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());//排序
vector<vector<int>> ret;
int n=nums.size();
for(int i=0;i<n;)
{
for(int j=i+1;j<n;)
{
int left=j+1,right=n-1;
long long flag=(long long)target-nums[i]-nums[j];
while(left<right)
{
int sum=nums[left]+nums[right];
if(sum<flag)
{
left++;
}
else if(sum>flag)
{
right--;
}
else
{
ret.push_back({nums[i],nums[j],nums[left],nums[right]});//插入数据
left++;
right--;
while(left<right&&nums[left]==nums[left-1])
{
left++;
}
while(left<right&&nums[right]==nums[right+1])
{
right--;
}
}
}
j++;
while(j<n&&nums[j]==nums[j-1])
{
j++;
}
}
i++;
while(i<n&&nums[i]==nums[i-1])
{
i++;
}
}
return ret;
}
};
小结:
对双指针算法的讲解就先告一段落啦,敬请期待下篇关于滑动窗口算法的介绍,欢迎各位大佬前来支持斧正!!!
热门推荐
数字经济与实体经济、虚拟经济的关系辨析
水上的公园城市:都江堰年供水76.4亿方,四川不息的“能量环”
RS485总线为什么要加终端电阻?
股票群是做什么的,如何参与?
狗狗晕车药指南(探究狗狗晕车药的类型和作用)
电影灵感:4个希腊神话故事
房产赠与法律效力全解析:赠与协议生效条件、撤销情形及财产追回规则
助力推动睡眠障碍筛查与公众健康意识提升
八字入门之甲木日干的喜忌 八字中甲木日干人生命运
瑜伽:舒缓痛经三体式
科普答疑-破水
项目经理如何给部门开会
重构"奶茶店":沉浸式场景设计的5个破局思路
疤痕增生修复需要怎么护理?
新生儿开八字的意义与方法 新生儿生辰八字解读指南
工艺角(Process Corner)详解:半导体制造中的关键概念
2025年网络安全零基础自学全攻略:避开弯路,快速上手!
春养肝,睡得香,春天多吃这8种食物,养肝排毒,睡得香!
春季肝病高发期:5个保养秘诀+饮食指南,轻松护肝不踩雷
肝左叶结节是什么病?医生专业解析病因、症状与治疗方案
租房合同哪些条款对承租人有利?
如何为女孩选择一个独特又 meaningful 的名字
苏美尔文明时间证据:揭示古代文明的神秘面纱
鉴别急慢性肾衰竭的检查方法
ILLIT出道专辑首周销量刷新K-POP女团纪录
aespa强势回归,主打歌《Whiplash》在韩国引发热潮
基于物联网的温室温湿度监控系统
智慧农业物联网开发方案:温湿度监控+自动化灌溉系统设计
手指前面的关节疼怎么回事
美媒预测总决赛夺冠概率!凯尔特人高达91.3%,独行侠仅为8.7%!