26. 删除排序数组中的重复项
方法一:快慢双指针
思路
设置快指针fast
和慢指针slow
,fast
负责检测元素是否重复,不重复则将其赋值给nums[slow]
。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int size = nums.size();
if (size <= 1) {
return size;
}
int slow = 1;
int fast = 1;
while (fast < size) {
if (nums[fast] == nums[fast - 1]) {
++fast;
} else {
nums[slow++] = nums[fast++];
}
}
return slow;
}
};
看完讲解的思考
无
代码实现遇到的问题
无
283. 移动零
方法一:快慢双指针
思路
设置快指针fast
和慢指针slow
,fast
负责检测元素是否为0,不为0则交换nums[slow]
和nums[fast]
,将非0元素移动到左端。
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int size = nums.size();
if (size <= 1) {
return;
}
int slow = 0;
int fast = 0;
while (fast < size) {
if (nums[fast] == 0) ++fast;
else swap(nums[slow++], nums[fast++]);
}
return;
}
};
看完讲解的思考
无
代码实现遇到的问题
无
844. 比较含退格的字符串
方法一:栈
思路
先分别计算两个输入会得到的字符串,再比较两个结果是否相等。
用栈来计算字符串的结果,遍历输入的每一个字符,如果不是#则入栈,如果是#则弹出栈顶字符,最终得到存储在栈中的字符串结果。
- 时间复杂度: O ( n + m ) O(n+m) O(n+m),n和m分别为两个字符串的长度。
- 空间复杂度: O ( n + m ) O(n+m) O(n+m),存储字符串结果的栈需要用到与输入同量级的空间。
C++代码
class Solution {
public:
bool backspaceCompare(string s, string t) {
stack<char> s1 = getResult(s);
stack<char> s2 = getResult(t);
return s1 == s2;
}
private:
stack<char> getResult(string input) {
int size = input.size();
stack<char> res;
for (int i = 0; i < size; ++i) {
if (input[i] != '#') {
res.push(input[i]);
} else {
if (!res.empty()) res.pop();
}
}
return res;
}
};
方法二:双指针原地修改字符串后一一比较
思路
自己想到的一个另类做法,当时是想着需要空间复杂度为
O
(
1
)
O(1)
O(1),用栈来保存字符串结果的话需要开辟额外空间,所以就想着原地修改字符串,这样就可以满足空间复杂度为
O
(
1
)
O(1)
O(1)。
原地修改字符串使得字符串右端为字符串结果,并返回字符串结果的长度,然后依次遍历字符串结果比较是否相等。
整体思路与方法一类似,只是把开辟额外空间存储结果改为了原地修改。
- 时间复杂度: O ( 2 ( n + m ) ) O(2(n+m)) O(2(n+m)),修改的时候需要遍历一次,比较的时候又需要遍历一次。
- 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
class Solution {
public:
bool backspaceCompare(string s, string t) {
int sSize = getFinalString(s);
int tSize = getFinalString(t);
if (sSize != tSize) return false;
for (int i = 0; i < sSize; ++i) {
if (s[i] != t[i]) return false;
}
return true;
}
private:
int getFinalString(string& s) {
int slow = 0;
int fast = 0;
int size = s.size();
while (fast < size) {
if (s[fast] == '#') {
++fast;
if (slow > 0) {
--slow;
}
} else {
s[slow++] = s[fast++];
}
}
return slow;
}
};
方法三:双指针一次遍历
思路
因为#只会影响前面的字符,不会影响后面的字符,所以对于两个字符串分别设立指针,从后往前遍历字符串。分别找到当前字符,比较两字符是否相等,不相等则返回false,若是其中一个字符串已经遍历完了,另外一个还没有,则也是返回false。
- 时间复杂度: O ( n + m ) O(n+m) O(n+m)
- 空间复杂度: O ( 1 ) O(1) O(1)
C++代码
自己一开始实现的双指针(又臭又长…但总归是AC了)
class Solution {
public:
bool backspaceCompare(string s, string t) {
int s_idx = s.size() - 1;
int t_idx = t.size() - 1;
int s_pass = 0;
int t_pass = 0;
while (s_idx >= 0 && t_idx >= 0) {
if (s[s_idx] == '#') {
--s_idx;
++s_pass;
} else if (t[t_idx] == '#') {
--t_idx;
++t_pass;
} else if (s_pass > 0) {
--s_idx;
--s_pass;
} else if (t_pass > 0) {
--t_idx;
--t_pass;
} else if (s[s_idx] != t[t_idx]) {
return false;
} else {
--s_idx;
--t_idx;
}
}
while (s_idx >= 0) {
if (s[s_idx] == '#') {
--s_idx;
++s_pass;
} else if (s_pass > 0) {
--s_idx;
--s_pass;
} else {
return false;
}
}
while (t_idx >= 0) {
if (t[t_idx] == '#') {
--t_idx;
++t_pass;
} else if (t_pass > 0) {
--t_idx;
--t_pass;
} else {
return false;
}
}
return true;
}
};
简洁版
class Solution {
public:
bool backspaceCompare(string s, string t) {
int s_idx = s.size() - 1;
int t_idx = t.size() - 1;
int s_pass = 0;
int t_pass = 0;
while (s_idx >= 0 || t_idx >= 0) {
// 找到当前字符
while (s_idx >= 0) {
if (s[s_idx] == '#') --s_idx, ++s_pass;
else if (s_pass > 0) --s_idx, --s_pass;
else break;
}
while (t_idx >= 0) {
if (t[t_idx] == '#') --t_idx, ++t_pass;
else if (t_pass > 0) --t_idx, --t_pass;
else break;
}
// 判断两字符是否相等
if (s_idx >= 0 && t_idx >= 0) {
if (s[s_idx] != t[t_idx]) return false;
} else {
if (s_idx >= 0 || t_idx >= 0) return false;
}
--s_idx, --t_idx;
}
return true;
}
};
看完讲解的思考
无
代码实现遇到的问题
方法三一开始实现用了三块while循环,没有想到怎么把这个三个while统一到一个while中
最后的碎碎念
昨晚出去聚餐了,导致刷了一半中断,第二天一早才补上,今天得双更了。