模型总结:前后指针法
零、前言
作者为了找工作和实习开启了自己的算法之旅,并将刷到的各种题型总结成模型分享给大家。
一、最基本的前后指针法
本文将持续更新。
27. 移除元素
1.使用场景
前后指针法,与其说是一个题型,不如说是一种思想:
在一个数组中筛选符合条件的元素,并放在原数组中。
2.思路
- 定义一个快指针和一个慢指针。
- 快指针依次遍历数组,在for循环内递增。
- 慢指针在快指针筛选出来符合条件的元素时,nums[slow]=nums[fast],slow++
- 总结来说就是slow筛选下标,而fast来筛选元素。
3.实现
class Solution {
public:
int removeElement(vector& nums, int val) {
int slowstr=0;//定义慢指针为数组下标
int faststr=0;//定义快指针指向所需的值
for(faststr=0;faststr<nums.size();faststr++)
{
if(nums[faststr]!=val)
{
nums[slowstr]=nums[faststr];
slowstr++;
}
}
return slowstr;
}
}; 在移除元素中就体现为移除满足条件的元素。然后再放在原数组中。
二、变式一:多元素去重
26. 删除有序数组中的重复项
1.思路
多元素去重,本质上就是筛选出数组中多个相等的元素。题目要求使用原数组,因此可以考虑前后指针法,只需要将slow++放在nums[slow]=nums[fast]之后即可。
2.实现
class Solution {
public:
void moveZeroes(vector& nums) {
int faststr=0;
int slowstr=0;
for(faststr=0;faststr<nums.size();faststr++)
{
if(nums[faststr]!=0)
{
nums[slowstr]=nums[faststr];
slowstr++;
}
}
for(int i=slowstr;i<faststr;i++)
{
nums[i]=0;
}
}
}; 本题给我们的启示为,当在相同数组中进行筛选的时候可以优先考虑前后指针法,这里给了条件是升序数组。所以说还需要有一定的条件,根据该条件来调整代码即可。
三、变式二:筛选元素具有某种属性
844. 比较含退格的字符串
1.思路
首先依然满足条件,筛选出来的元素存放在原数组中,而具有某种属性最终会体现在slow指针如何处理上。fast指针继续正常遍历即可。
在这里每当发生退格的时候,slow--,并且当--为小于0的数时,将其置为0。
2.实现
class Solution {
public:
string StrSolution(string str)
{
int faststr=0;
int slowstr=0;
for(faststr=0;faststr<str.size();faststr++)
{
if(slowstr<0)
{
slowstr=0;
}
if(str[faststr]!='#')
{
str[slowstr]=str[faststr];
slowstr++;
}
else
{
slowstr--;
}
}
if(slowstr<0)
{
slowstr=0;
}
str[slowstr]='\0';
str = str.substr(0, slowstr);
return str;
}
bool backspaceCompare(string s, string t) {
string s1=StrSolution(s);
string s2=StrSolution(t);
if(s1==s2)
{
return true;
}
else
{
return false;
}
}
}; 3.发现的问题
其中如果不使用字符串切割,string类不会因为看到'\0'而结束。但是如果在构造的时候有'\0'那么可以结束。因此还需要进行字符串切割。
四、总结
前后指针法不是一个固定的题型,重要点在于识别。
- 当发现存放的元素放在原数组中的时候,就可以考虑使用前后指针法了。往往还伴随着一些条件。
- 筛选的元素可以带有一些属性,使用slow指针来体现。
本文将持续进行更新。

