力扣复健第一天~从看似比较简单的双指针开始(实际并没有)
27.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
1. 快慢指针
这也是比较经典和舒服的解法,但是第一次思考觉得还是有点困难(x
注意slow指针只负责统计数量,把符合条件的一个个填充到slow指针指的地方。
而fast指针是循环变量,同时也是判断的关键,判断是不是val
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n=nums.size();
int slow=0,fast=0;
for(fast=0;fast<n;fast++)
{
if(nums[fast]!=val)
{
nums[slow++]=nums[fast];
}
}
return slow;
}
};
2. 从后往前的双指针
这是元素替代一题想到的方法,一个指针i指向要填充的地方,j从后往前对i处进行填充。注意j处一定不能是val,所以一定要先用循环把它过滤一下,最初的j一定要指向非val
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n=nums.size();
if(n<=0) return 0;
// i指向当前,j指向末尾
int j=n-1;
while(j>=0&&nums[j]==val)
{
j--;
}
for(int i=j;i>=0;i--)
{
if(nums[i]==val)
{
nums[i]=nums[j];
j--;
}
}
return j+1;
}
};
26.删除排序数组中的重复项
继续贯彻了上一题快慢指针的思想:
注意slow指针只负责统计数量,把符合条件的一个个填充到slow指针指的地方。
而fast指针是循环变量,同时也是判断的关键 到底该不该把fast上的元素给slow,就看fast指针指的值是否符合要求。
这题里,如果fast指针的上一个值和现在的值不同,说明这是一个“边界”,也就是新值,非重复值,此时可以赋给nums[slow]
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int n=nums.size();
if(n==0||n==1) return n;
int slow=1,fast=1;
while(slow<n&&fast<n)
{
if(nums[fast]!=nums[fast-1])
{
nums[slow]=nums[fast];
slow++;
}
fast++;
}
return slow;
}
};
844.比较含退格的字符串
这题的要求是空间O(1)
如果是O(m+n) 那么我们开两个字符串,存入最终结果比较一下就好了
1. 空间O(m+n)
ps.用栈更方便
class Solution {
public:
bool backspaceCompare(string s, string t) {
int spos=-1,tpos=-1;
// int lens=s.length(),lent=t.length();
string ss,tt;
for(char c:s)
{
if(c!='#')
{
ss+=c;
spos++;
}
else
{
if(spos>=0)
{
ss.erase(spos,1);
spos--;
}
}
}
for(char c:t)
{
if(c!='#')
{
tt+=c;
tpos++;
}
else
{
if(tpos>=0)
{
tt.erase(tpos,1);
tpos--;
}
}
}
// cout<<ss<<" "<<tt<<endl;
return tt==ss;
}
};
2. 空间O(1)
复健第一天表示还是难写啊qaq
- 先找到s中第一个要比较的字符
- 找t中第一个要比较的字符
- i>=0 j>=0的条件下(防止第一个字符为# 那么下标减出来是负数) 如果两个字符比较为不同,立刻false
- i,j一种已经到头,另一种没到,说明没匹配上,也是false
- i–,j-- 下一个循环
class Solution {
public:
bool backspaceCompare(string s, string t) {
int lens=s.length();
int lent=t.length();
int i=lens-1;
int j=lent-1;
int skipS=0,skipT=0;
while(i>=0||j>=0)
{
//找到S中的第一个可比较字符
while(i>=0)
{
if(s[i]=='#')
{
skipS++;
i--;
}
else if(skipS>0)
{
skipS--;
i--;
}
else break;
}
//找到T中的第一个可比较字符位置
while(j>=0)
{
if(t[j]=='#')
{
skipT++;
j--;
}
else if(skipT>0)
{
skipT--;
j--;
}
else break;
}
if(i>=0&&j>=0)
{
if(s[i]!=t[j]) return false;
}
else if(i>=0||j>=0)
{
return false;
}
i--;j--;
}
return true;
}
};
977. 有序数组的平方
最大值只能是在数组的两遍,所以用两个指针,一个指向最左,一个最右。
开一个同样大小的数组,从末尾向前填空
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int n=nums.size();
vector<int> res(n,0);
int i=0,j=n-1;
int pos=n-1,t1,t2;
while(i<=j)
{
t1=nums[i]*nums[i];
t2=nums[j]*nums[j];
if(t1>=t2)
{
res[pos--]=t1;
i++;
}
else
{
res[pos--]=t2;
j--;
}
}
return res;
}
};