✨✨✨学习的道路很枯燥,希望我们能并肩走下来!
文章目录
目录
前言
本篇详细介绍了双指针的使用,让使用者了解双指针算法,而不是仅仅停留在表面,更好的模拟,为了更好的使用. 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!
提示:以下是本篇文章正文内容,下面案例可供参考
一、双指针算法是什么?
常见的双指针有三种形式:前后指针、对撞指针、快慢指针
双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描,从而达到相应的目的。
换言之,双指针法充分使用了数组有序这一特征,从而在某些情况下能够简化一些运算。(往往能降低一个次方的时间复杂度)
1.1 对撞指针
对撞指针是指在数组中,将指向最左侧的索引定义为左指针(left)
,最右侧的定义为右指针(right)
,然后从两头向中间进行数组遍历。
对撞数组适用于连续数组和字符串,也就是说当你遇到题目给定连续数组和字符床时,应该第一时间想到用对撞指针解题。
1.2 快慢指针
快慢指针也是双指针,但是两个指针从同一侧开始遍历数组,将这两个指针分别定义为快指针(fast)
和慢指针(slow)
,两个指针以不同的策略移动,直到两个指针的值相等(或其他特殊条件)为止,如 fast 每次增长两个,slow 每次增长一个。
1.3 前后指针
1、前后指针:用于顺序结构,一般是两个指针同方向,cur指针用来遍历数组,des指针将数组进行区域划分。(如1、2题)
二、双指针算法的应用
2.1 移动零
class Solution {
public:
void moveZeroes(vector<int>& nums) {
for(int cur = 0,dest = -1;cur<nums.size();cur++)
{
if(nums[cur])//处理非0元素
swap(nums[++dest],nums[cur]);
}
}
};
2.2 复写0
class Solution {
public:
void duplicateZeros(vector<int>& arr) {
int cur = 0, dest = -1 , n = arr.size();
//1.找最后一个复写的数
while(cur<n)
{
if(arr[cur])
dest++;
else
dest+=2;
if(dest>=n-1)
break;
cur++;
}
//2. 处理边界问题(即cur移动到数组最后一个位置,该位置为0
if(dest == n)
{
arr[n-1]=0;
cur--;
dest-=2;
}
//3 从右向左复写
while(cur>=0)
{
if(arr[cur])
arr[dest--]=arr[cur--];
else
{
arr[dest--] = 0;
arr[dest--] = 0;
cur--;
}
}
}
};
2.3 快乐数
class Solution {
public:
int Sum(int n)
{
int sum = 0;
while(n)
{
int t = n%10;
sum += t*t;
n /= 10;
}
return sum;
}
bool isHappy(int n) {
int slow = n ,fast = Sum(n);
while(slow != fast)
{
slow = Sum(slow);
fast = Sum(Sum(fast));
}
return slow == 1;
}
};
2.4 盛最多水的容器
class Solution {
public:
int maxArea(vector<int>& height) {
int left = 0, right = height.size()-1 , ret = 0;
while(left<right)
{
int v = min(height[left],height[right])*(right-left);
ret = max(ret,v);
if(height[left]<height[right])
left++;
else
right--;
}
return ret;
}
};
2.5 有效三角形的个数
class Solution {
public:
int triangleNumber(vector<int>& nums) {
//1.优化区间
sort(nums.begin(),nums.end());
//2.固定最大值
int ret = 0, n = nums.size();
for(int i = n-1;i>=2;i--)
{
//3.利用双指针快速统计符合要求的三元组的个数
int left = 0, right = i-1;
while(left<right)
{
if((nums[left]+nums[right])>nums[i])
{
ret+= right - left;
right--;
}
else
{
left++;
}
}
}
return ret;
}
};
2.6 查找总价格为目标值的两个商品
LCR 179. 查找总价格为目标值的两个商品 - 力扣(LeetCode)
class Solution {
public:
vector<int> twoSum(vector<int>& price, int target) {
int left = 0,right = price.size()-1;
while(left<right)
{
if((price[left]+price[right])<target)
left++;
else if((price[left]+price[right])>target)
right--;
else
return {price[left],price[right]};//隐式类型转化
}
//考虑编译器,解决:non-void function does not return a value in all control paths,让所有路径都有返回值
return {};
}
};
2.6 三数之和
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
//排序,方便我们
sort(nums.begin(),nums.end());
//2.固定
vector<vector<int>> ret;
int n = nums.size();
for(int i = 0;i<n;)
{
if(nums[i]>0) break; //优化固定区间
int left = i+1;
int right = n-1;
int 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--;
}
}
i++;//越界问题处理+去重
while(i<n&&nums[i]==nums[i-1]) i++;
}
return ret;
}
};
2.7 四数之和
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
//1.排序
sort(nums.begin(),nums.end());
//2.双指针
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;
int right = n-1;
long long aim = (long long)target - nums[i]-nums[j]; //用longlong防止数据溢出
while(left<right)
{
int sum = nums[left]+nums[right];
if(sum>aim) right--;
else if(sum<aim) left++;
else
{
ret.push_back({nums[i],nums[j],nums[left++],nums[right--]});
//去重1
while(left<right&&nums[left]==nums[left-1]) left++;
while(left<right&&nums[right]==nums[right+1]) right--;
}
}
//去重2
j++;
while(j<n&&nums[j]==nums[j-1]) j++;
}
//去重3
i++;
while(i<n&&nums[i]==nums[i-1]) i++;
}
return ret;
}
};
总结
✨✨✨各位读友,本篇分享到内容是否更好的让你理解了双指针算法,如果对你有帮助给个👍赞鼓励一下吧!!
🎉🎉🎉世上没有绝望的处境,只有对处境绝望的人。
感谢每一位一起走到这的伙伴,我们可以一起交流进步!!!一起加油吧!!。