我们还有更长的路要走,不过没关系,道路就是生活。
前言
这是我自己刷算法题的第一篇博客总结。
后期我会继续把刷算法题的笔记开源至博客上。
技巧
1. 双指针算法,但实际上是利用数组下标来充当指针,并不是直接使用指针。
2. cur指针,扫描遍历指针,左边是已经扫描遍历的部分,中间及右边是还未扫描遍历的部分。
3. dest指针,分隔指针,左边是已经排好的序的部分,中间及右边是还未排序的部分。
4. 划分为三个区间:[0,dest-1],[dest,cur-1],[cur,n-1]。
5. 双指针算法分为两类:就地操作和异地操作,可以先异地操作,最后优化成就地操作。
6. 就地操作不需要重新创建一个数组,但是需要考虑覆盖问题。异地操作需要重新创建一个数组,但是不用考虑覆盖问题。
7. 双指针算法可以从前到后遍历,又可以从后到前遍历。
8. 双指针算法又可以变形为快慢指针,一个移动快的指针,一个移动慢的指针。
9. 双指针算法还可以变形为相撞指针,两个指针相向而行,最终走到一起,共同遍历数组。相撞指针一般需要先排序,然后利用单调性,两个指针从两边向中间遍历。
例题
1. leetcode-283题: 283. 移动零 - 力扣(LeetCode)
https://leetcode.cn/problems/move-zeroes/
void moveZeroes(vector<int>& nums)
{
int cur=0,dest=0;
while(cur<nums.size())
{
if(nums[cur]!=0)
{
swap(nums[cur],nums[dest]);
cur++;
dest++;
}
else
{
cur++;
}
}
}
2. leetcode-1089题: 1089. 复写零 - 力扣(LeetCode)
https://leetcode.cn/problems/duplicate-zeros/
class Solution {
public:
void duplicateZeros(vector<int>& arr)
{
int cur=0,dest=0;
while(dest<arr.size())
{
if(arr[cur]!=0)
{
cur++;
dest++;
}
else
{
cur++;
dest+=2;
}
}
if(dest>arr.size())
{
dest=arr.size()-1;
arr[dest]=0;
cur-=2;
dest--;
while(cur>=0)
{
if(arr[cur]!=0)
{
arr[dest]=arr[cur];
dest--;
cur--;
}
else
{
arr[dest]=0;
arr[dest-1]=0;
dest-=2;
cur--;
}
}
}
else
{
dest=arr.size()-1;
cur--;
while(cur>=0)
{
if(arr[cur]!=0)
{
arr[dest]=arr[cur];
dest--;
cur--;
}
else
{
arr[dest]=0;
arr[dest-1]=0;
dest-=2;
cur--;
}
}
}
}
};
3. leetcode-208题:
202. 快乐数 - 力扣(LeetCode)
https://leetcode.cn/problems/happy-number/
class Solution
{
public:
int ADD(int n)
{
int sum=0;
while(n>=10)
{
sum+=(n%10)*(n%10);
n=n/10;
}
sum+=n*n;
return sum;
}
bool isHappy(int n)
{
int slow=n,fast=ADD(n);
while(slow!=fast)
{
slow=ADD(slow);
fast=ADD(fast);
fast=ADD(fast);
}
if(fast==1)
{
return true;
}
else
{
return false;
}
}
};
4. leetcode-11题:
class Solution
{
public:
int Min(int x,int y)
{
return x<=y?x:y;
}
int Max(int x,int y)
{
return x>=y?x:y;
}
int maxArea(vector<int>& height)
{
int s=0;
int left=0,right=height.size()-1;
while(left!=right)
{
s=Max((right-left)*Min(height[right],height[left]),s);
if(height[left]<height[right])
{
left++;
}
else
{
right--;
}
}
return s;
}
};
5. leetcode-611题:
611. 有效三角形的个数 - 力扣(LeetCode)
https://leetcode.cn/problems/valid-triangle-number/
class Solution
{
public:
int triangleNumber(vector<int>& nums)
{
int ret=0;
sort(nums.begin(),nums.end());
for(int last=nums.size()-1;last>1;last--)
{
int left=0,right=last-1;
while(left<right)
{
while(nums[right]+nums[right-1]>nums[last])
{
if(nums[left]+nums[right]>nums[last])
{
ret=ret+(right-left);
break;
}
else
{
left++;
}
}
right--;
}
}
return ret;
}
};
6. leetcode-179题:
class Solution {
public:
vector<int> twoSum(vector<int>& price, int target)
{
int left=0,right=price.size()-1;
while(price[left]+price[right]!=target)
{
if(price[left]+price[right]<target)
{
left++;
}
else
{
right--;
}
}
vector<int> arr;
arr.push_back(price[left]);
arr.push_back(price[right]);
return arr;
}
};
7. leetcode-15题:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
vector<vector<int>> set;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();)
{
if(nums[i]>0)
{
break;
}
int left=i+1,right=nums.size()-1,target=-nums[i];
while(left<right)
{
if(nums[left]+nums[right]<target)
{
left++;
}
else if(nums[left]+nums[right]>target)
{
right--;
}
else
{
set.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<nums.size()&&nums[i]==nums[i-1])
{
i++;
}
}
return set;
}
};
8. leetcode-18题:
18. 四数之和 - 力扣(LeetCode)
https://leetcode.cn/problems/4sum/description/
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target)
{
sort(nums.begin(),nums.end());
vector<vector<int>> set;
if(nums.size()<4)
{
return set;
}
int first=0;
while(first<nums.size()-3)
{
int second=first+1;
while(second<nums.size()-2)
{
int left=second+1,right=nums.size()-1;
long long tar=(long long)target-nums[first]-nums[second];
while(left<right)
{
if(nums[left]+nums[right]<tar)
{
left++;
}
else if(nums[left]+nums[right]>tar)
{
right--;
}
else
{
set.push_back({nums[first],nums[second],nums[left],nums[right]});
left++;
right--;
while(left<right&&nums[left]==nums[left-1])
{
left++;
}
while(left<right&&nums[right]==nums[right+1])
{
right--;
}
}
}
second++;
while(second<nums.size()-2&&nums[second]==nums[second-1])
{
second++;
}
}
first++;
while(first<nums.size()-3&&nums[first]==nums[first-1])
{
first++;
}
}
return set;
}
};
致谢
感谢您花时间阅读这篇文章!如果您对本文有任何疑问、建议或是想要分享您的看法,请不要犹豫,在评论区留下您的宝贵意见。每一次互动都是我前进的动力,您的支持是我最大的鼓励。期待与您的交流,让我们共同成长,探索技术世界的无限可能!