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;
    }
};
posted @ 2022-10-12 17:30  光風霽月  阅读(151)  评论(0编辑  收藏  举报