双指针法:用两个指针一个循环来完成(有时候两个循环才能完成的)一件事情
反转链表(一指针在前,一指针在后)
https://leetcode-cn.com/problems/reverse-linked-list/submissions/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre=NULL,*cur=head;
while(cur!=NULL)
{
ListNode* temp=cur->next;
cur->next=pre;
pre=cur;
cur=temp;
}
return pre;
}
};
反转字符串(数组最前一个指针,最后一个指针,两个指针最后汇聚在一起)
https://leetcode-cn.com/problems/reverse-string/submissions/
class Solution {
public:
void swap(char& a,char& b)
{
char temp=a;
a=b;
b=temp;
}
void reverseString(vector<char>& s) {
if(s.size()==1) return;
for(int i=0,j=s.size()-1;i<=(s.size()-2)/2;i++,j--)
{
swap(s[i],s[j]);
}
}
};
移除元素(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/remove-element/submissions/
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow=0;
for(int fast=0;fast<nums.size();fast++)
{
if(nums[fast]==val) continue;
else
{
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
};
注意C语言的逻辑运算符(&& ||)是从左到右运算的
删除有序数组中的重复项(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==0) return 0;
int slow=0;
for(int fast=0;fast<nums.size();fast++)
{
if(nums[fast]==nums[slow]) continue;
else
{
nums[++slow]=nums[fast];
}
}
return slow+1;
}
};
移动零(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/move-zeroes/
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slow=0;
for(int fast=0;fast<nums.size();fast++)
{
if(nums[fast]==0) continue;
else
{
nums[slow]=nums[fast];
slow++;
}
}
while(slow<nums.size())
{
nums[slow]=0;
slow++;
}
}
};
比较含退格的字符串(一个快指针用于筛选出想要的元素,一个慢指针用于保存答案)
https://leetcode-cn.com/problems/backspace-string-compare/submissions/
class Solution {
public:
bool backspaceCompare(string s, string t) {
if(dealStr(s)==dealStr(t)) return true;
else return false;
}
string dealStr(string str)
{
string ans;
int slow=0;
for(int fast=0;fast<str.size();fast++)
{
if(str[fast]!='#') //增加一个字符
{
str[slow]=str[fast];
slow++;
}
else
{
if(slow>0) slow--; //减少一个字符
}
}
for(int i=0;i<slow;i++)
{
ans+=str[i];
}
return ans;
}
};
有序数组的平方(数组最前一个指针,最后一个指针,两个指针最后汇聚在一起)
https://leetcode-cn.com/problems/squares-of-a-sorted-array/
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> ans(nums.size()); //默认值为0
for(int i=0,j=nums.size()-1,pos=nums.size()-1;i<=j;)
{
if(nums[i]*nums[i]>=nums[j]*nums[j])
{
ans[pos--]=nums[i]*nums[i];
i++;
}
else
{
ans[pos--]=nums[j]*nums[j];
j--;
}
}
return ans;
}
};
滑动窗口法:在题目中有连续的子序列这一描述时,可以考虑使用
长度最小的子数组(滑动窗口法,也是快慢指针法中的一类)
https://leetcode-cn.com/problems/minimum-size-subarray-sum/
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int slow=0,result=INT32_MAX,sum=0; //sum用于记录当前序列的和
for(int fast=0;fast<nums.size();fast++)
{
sum+=nums[fast];
while(sum>=target) //当前序列符合要求
{
//更新答案
int len=fast-slow+1; //当前符合要求的序列的长度
if(result>len) result=len;
//滑动窗口向前缩小
sum-=nums[slow];
slow++;
}
}
if(result==INT32_MAX) return 0;
else return result;
}
};
水果成篮(滑动窗口法,也是快慢指针法中的一类)
https://leetcode-cn.com/problems/fruit-into-baskets/
class Solution {
public:
int totalFruit(vector<int>& fruits) {
map<int,int> dict; //记录现在共有多少水果类型,每个类型有多少颗
int slow=0,result=0;
for(int fast=0;fast<fruits.size();fast++)
{
//当前水果种类数<2,往dict里面新加水果
if(dict.size()<2)
{
//是新的一类水果
if(!dict.count(fruits[fast]))
{
dict[fruits[fast]]=1;
}
else
{
dict[fruits[fast]]++;
}
//当前子序列长度
int len=fast-slow+1;
//更新答案
result=result<len?len:result;
}
//dict已满,但是里面已有同类型的水果
else if(dict.size()==2&&dict.count(fruits[fast]))
{
dict[fruits[fast]]++;
//当前子序列长度
int len=fast-slow+1;
//更新答案
result=result<len?len:result;
}
//dict已满,开始缩小窗口
else
{
while(dict.size()==2)
{
//窗口向前移动
dict[fruits[slow]]--;
//若该种果实数目为0,则从dict中删除
if(dict[fruits[slow]]==0)
{
dict.erase(fruits[slow]);
}
slow++;
}
//fast指针不动
fast-=1;
}
}
return result;
}
};
三数之和(排序+双指针)
https://leetcode-cn.com/problems/3sum/
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++)
{
if(i==0||nums[i]!=nums[i-1])
{
int left=i+1,right=nums.size()-1;
while(left<right)
{
if(nums[i]+nums[left]+nums[right]<0)
{
while(left<right&&nums[left+1]==nums[left]) left++;
left++;
}
else if(nums[i]+nums[left]+nums[right]>0)
{
while(left<right&&nums[right-1]==nums[right]) right--;
right--;
}
else
{
ans.push_back({nums[i],nums[left],nums[right]});
//去重
while(left<right&&nums[left+1]==nums[left]) left++;
while(left<right&&nums[right-1]==nums[right]) right--;
left++;
right--;
}
}
}
}
return ans;
}
};
四数之和
https://leetcode-cn.com/problems/4sum/
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++)
{
if(i==0||nums[i]!=nums[i-1])
{
for(int j=i+1;j<nums.size();j++)
{
if(j==i+1||nums[j]!=nums[j-1])
{
int left=j+1,right=nums.size()-1;
while(left<right)
{
long long a=nums[i],b=nums[j],
c=nums[left],d=nums[right],mytarget=target;
if(a+b+c+d<mytarget)
{
while(left<right&&nums[left+1]==nums[left]) left++;
left++;
}
else if(a+b+c+d>mytarget)
{
while(left<right&&nums[right-1]==nums[right]) right-- ;
right--;
}
else
{
ans.push_back({nums[i],nums[j],nums[left],nums[right]});
while(left<right&&nums[left+1]==nums[left]) left++;
left++;
while(left<right&&nums[right-1]==nums[right]) right-- ;
right--;
}
}
}
}
}
}
return ans;
}
};