双指针算法系列:一快一慢解决两数之和、三数之和与四数之和
创作时间:
作者:
@小白创作中心
双指针算法系列:一快一慢解决两数之和、三数之和与四数之和
引用
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;
}
};
小结:
对双指针算法的讲解就先告一段落啦,敬请期待下篇关于滑动窗口算法的介绍,欢迎各位大佬前来支持斧正!!!
热门推荐
江油肥肠:从街边小吃到非遗美食的传奇之路
血压偏低心跳偏快是什么原因
周末打卡安阳:殷墟+太行山大峡谷,两天一夜完美攻略
秋冬打卡王相岩:安阳最美摄影点
“离婚宣告”拯救不了婚姻 但能让离婚更温情有爱
房間跳蚤怎麼除?床有跳蚤怎麼處理?跳蚤怕什麼?會自己消失嗎?
美食三步法之午餐篇——清蒸螃蟹
白萝卜种植技术及管理
李白的浪漫主义:从艺术特色到精神内涵
李白诗歌修辞艺术大揭秘:夸张衬托反问全都有!
一穴舒缓心悸、胸闷、胃胀:花莲慈院中医部养生教学“十总穴之养心穴”
恶心怎么办?专业医生教你这样缓解
孕妇孕吐怎么办?这些自然疗法或许能帮到你
“南北接力”创新养殖模式 助力黑龙江小龙虾产业蓬勃发展
东北蝲蛄身价几何?从生态环境到餐桌的深度解析
对蛋白粉检测项目与标准的全面解析
家有退役军人的恭喜!优待证用途越来越广,要妥善保管!
冬日暖阳之旅:厦门旅游全攻略
李健:用歌声诠释古典诗词之美
李健的民谣风为何如此治愈?
猪肉常见部位的特点及吃法,看这一篇就够了
如何是最好的离婚方式
离婚方式及关键问题详解
协议离婚和诉讼离婚的区别
周末聚餐:特色下饭瓦块鱼攻略
专家教你:三步辨识最新鲜的鱼
清蒸鱼头:家宴必备美味
澳洲银鲈的三种烹饪方式:清蒸、红烧还是生吃?
元旦诗词里的新年祝福
【辟谣】领基本养老金要缴税?假的!