Leetcode 844 -- 双指针&&O(1)时间复杂度
题目描述
思路
这里主要考虑 O(1) 空间复杂度的做法。
一个字符是否会被删掉,只取决于该字符后面的退格符,而与该字符前面的退格符无关。因此当我们逆序地遍历字符串,就可以立即确定当前字符是否会被删掉。
只要能看出来倒序,就解决了一半了,剩下的主要是如何用代码实现。
有很多细节,详细看代码注释。
官方题解
代码
class Solution {
public:
bool backspaceCompare(string s, string t) {
int n = s.size(), m = t.size();
int skips = 0, skipt = 0; // 标识跳过的字符个数
int i, j;
// 为什么for循环中的判断要用 i>=0||j>=0 而不是 i>=0&&j>=0呢?
// 考虑一种边界情况:在for循环中,i遍历到了第1个字符,j遍历到了第0个字符,它们相等,继续下一次循环
// 再经过 i--, j -- 之后,i=0,j=-1
// 可以发现j已经不符合条件了,for结束,最后返回true
// 但很明显,i还没遍历完啊
// 不过!不要想当然的以为此时就不匹配了!
// 因为i剩下的字符可能全都被退格!此时返回true
// 也有可能最终剩下几个字符无法匹配,此时返回false
for(i = n - 1, j = m - 1; i >= 0 || j >= 0; i -- , j -- )
{
// 因为在这个for循环内部,每一次我们都要比较s和t没被删除的字符是否相等
// 所以我们要找到s和t中不为'#'的字符
while(i >= 0) {
if(s[i] == '#') // 是退格符
{
skips ++ , i -- ; // i -- 继续往下找
}
else if(skips)
{
skips -- , i -- ; // 虽然不是退格符,但是由于需要回退,所以这个字符要被删除,且继续往下找
}
else // 不需要回退
{
break;
}
}
while(j >= 0) {
if(t[j] == '#')
{
skipt ++ , j -- ;
}
else if(skipt)
{
skipt -- , j -- ;
}
else
{
break;
}
}
if(i >= 0 && j >= 0) {
if(s[i] != t[j]) return false;
}
else {
if(i >= 0 || j >= 0) // 说明一个字符串遍历完了,另一个字符串还没遍历完,肯定不相等
return false;
}
}
// for done
return true;
}
};