1.双指针
采用数组分块的思想

bash
void moveZeroes(vector<int>& nums) {
for(int cur=0,dst=-1;cur<nums.size();cur++)
{
//[0,dst]非0,[dst+1,cur-1]为0
if(nums[cur]) swap(nums[++dst],nums[cur]);
}
}

分析题目:由前向后会导致数据覆盖,因此采用由后向前,需要先找到最后一个数字,处理特殊情况,然后进行覆写
bash
void duplicateZeros(vector<int>& arr) {
//1.找到最后一个位置
int cur=0,dst=-1;
while(cur<arr.size())
{
if(arr[cur]==0) dst+=2;
else dst++;
if(dst>=arr.size()-1) break;
cur++;
}
//2.进行覆写
//判断dst是否越界,进行越界处理
if(dst==arr.size())
{
arr[dst-1]=0;
dst-=2;
cur--;
}
//开始覆写
while(cur>=0)
{
if(arr[cur]==0)
{
arr[dst--]=0;
arr[dst--]=0;
cur--;
}
else
{
arr[dst--]=arr[cur--];
}
}
}

很显然这题是用快慢指针,很常规
bash
int SumSqueue(int m)
{
int sum=0;
while(m)
{
sum+=pow(m%10,2);
m/=10;
}
return sum;
}
bool isHappy(int n) {
int fast=SumSqueue(n);
int slow=n;
while(slow!=fast)
{
fast=SumSqueue(SumSqueue(fast));
slow=SumSqueue(slow);
}
if(fast==1) return true;
else return false;
}

本题使用对撞指针来解,分情况讨论,每次都选择可能比上一次体积更大的情况
bash
int maxArea(vector<int>& height) {
int left=0,right=height.size()-1,ret=0;
while(left<right)
{
int v=min(height[right],height[left])*(right-left);
ret=max(ret,v);
if(height[left]<height[right]) left++;
else right--;
}
return ret;
}

满足两边之和大于最长边即可组成三角形,我们可以将数组排序,三层遍历暴力求解会超时,进行优化。控制最长边,在左区间进行取舍
bash
int triangleNumber(vector<int>& nums) {
sort(nums.begin(),nums.end());
int ret=0,n=nums.size();
for(int i=2;i<n;i++)//固定最大的边
{
int left=0,right=i-1;
while(left<right)//对撞剩余两条边
{
if(nums[left]+nums[right]>nums[i])
{
ret+=right-left;
right--;
}
else
{
left++;
}
}
}
return ret;
}

固定一个数,其余两数相加之和等于这个数的相反数即可,注意跳过重复的元素
bash
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(),nums.end());
for(int i=nums.size()-1;i>1;i--)
{
int j=0,k=i-1;
int ret=-nums[i];
while(j<k)
{
if(nums[j]+nums[k]==ret)
{
res.push_back({nums[i],nums[j],nums[k]});
j++,k--;
while(j<k&&nums[j]==nums[j-1]) j++;
while(j<k&&nums[k]==nums[k+1]) k--;
}
else if(nums[j]+nums[k]<ret) j++;
else k--;
}
while(i>1&&nums[i]==nums[i-1]) i--;
}
return res;
}
2. 滑动窗口
滑动窗口本质还是双指针,只不过换了一种用法,我们之前做过对撞指针,快慢指针和分区指针这个也是类似的用法,

解题时注意符合要求时更新结果,如果不满足条件就滑动左边窗口
int minSubArrayLen(int target, vector<int>& nums) {
int n=nums.size();
int left=0,right=0,ret=INT_MAX;
int sum=0;
while(right<n)
{
sum+=nums[right];
while(sum>=target)
{
ret=min(ret,right-left+1);
sum-=nums[left++];
}
right++;
}
return ret==INT_MAX?0:ret;
}
438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

这个要固定窗口的长度,定义两个哈希表来存储s字符串和p字符串的信息,用count计数来判断是否满足子串的条件,进窗口维护count,出窗口维护count
vector<int> findAnagrams(string s, string p) {
int hash2[128]={0},hash1[128]={0};
for(auto e:p) hash2[e-'a']++;
int m=p.size();
int n=s.size();
int left=0,right=0,count=0;
vector<int>ret;
while(right<n)
{
char out=s[right];
hash1[out-'a']++;
if(hash1[out-'a']<=hash2[out-'a']) count++;
while(right-left+1>m)
{
if(hash1[s[left]-'a']<=hash2[s[left]-'a']) count--;
hash1[s[left++]-'a']--;
}
if(count==m) ret.push_back(left);
right++;
}
return ret;
}

这题和字母异位词类似,不同点是窗口不是固定的,而是滑动的,满足条件时更新chuangko
int hash1[128]={0};int hash2[128]={0};
int left=0,right=0,len=INT_MAX,retlen=-1,count=0;
for(auto e:t) hash2[e]++;
while(right<s.size())
{
char in=s[right];
hash1[in]++;
if(hash1[in]<=hash2[in]) count++;
while(count==t.size())
{
if(right-left+1<len)
{
retlen=left;
len=right-left+1;
}
char out=s[left++];
if(hash1[out]<=hash2[out]) count--;
hash1[out]--;
}
right++;
}
if(len==INT_MAX) return "";
else return s.substr(retlen,len);
}