双指针算法系列:一快一慢解决两数之和、三数之和与四数之和
创作时间:
作者:
@小白创作中心
双指针算法系列:一快一慢解决两数之和、三数之和与四数之和
引用
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;
}
};
小结:
对双指针算法的讲解就先告一段落啦,敬请期待下篇关于滑动窗口算法的介绍,欢迎各位大佬前来支持斧正!!!
热门推荐
需求理论在管理中的应用
马斯洛的需求层次理论的意义
健身增肌困难?中医助你突破瓶颈,打造理想体态!
让孩子变聪明的18个方法:从权威到创新,全面发展孩子的潜能
AI让生活更便捷:智能家居、健康监测到智能导航全覆盖
中国发布人工智能治理倡议,AI大模型引领产业变革新浪潮
甲胎蛋白的逆袭之路:科学降甲,守护健康
甲胎蛋白偏高意味着什么
2024年小规模纳税人如何交税?小额企业还可以免税!
别让嵌甲变甲沟炎!正确修剪趾甲,远离灰指甲困扰
饮食不当,肚子抗议!这些坏习惯你中了吗?
埃里克森人生八阶段理论:婴儿期的心理发展任务与危机
楚雄市市场监管局:多措并举提升小作坊管理水平
太原市尖草坪区市场监管局开展食品加工小作坊专项检查行动
为什么得肝癌的人越来越多?预防肝癌,要做好这4点
乙肝小三阳甲胎蛋白偏高严重吗
川菜大师亲授:五花肉回锅肉的完美烹饪指南
律师追债成功率揭秘:从专业能力到证据准备
QMS是什么:提升企业质量管理
打造意式极简家居:从色彩到智能家居的全方位指南
凌乱家庭环境影响儿童心理健康,专家建议定期整理
现代简约风K&K公寓:每个空间都在促进情感交流
田园风格装修:自然材料与柔和色调的完美融合
2025军考备考指南:750分考试内容详解与备考建议
更年期症候群中医调理:肝脾肾是关键,4款养生食谱助你缓解不适
焦虑情绪竟让你肚子疼?
饮食不当惹祸,小心肚子疼找上门!
东方市冬季风力变化揭秘:特征、影响与应对
豫园城隍庙见证上海700年沧桑,老城厢保护传承正当时
如何设置电脑开机密码以保护个人隐私和信息安全