844. 比较含退格的字符串
题目:https://leetcode-cn.com/problems/backspace-string-compare/
想法:先将每一个字符串处理完再比较;利用队列(还未实现)
代码:
C++版本: bool backspaceCompare(string s, string t) { for (int j = 0, i = 0; i < s.size(); ){ if (s[i] == '#'){ s[j] = '#'; i++; while (j > 0 && s[j] == '#') j--; }else{ j = i; i++; } } for (int j = 0, i = 0; i < t.size(); ){ if (t[i] == '#'){ t[j] = '#'; i++; while (j > 0 && t[j] == '#') j--; }else{ j = i; i++; } } bool result = true; int i = 0, j = 0; while ( i < s.size() || j < t.size()){ if (s[i] != '#' && t[j] != '#' && s[i] != t[j]){ result = false; break; } else if (s[i] == '#'){ i++; } else if (t[j] == '#'){ j++; }else { i++; j++; } } return result; }
官方解法:https://leetcode-cn.com/problems/backspace-string-compare/solution/bi-jiao-han-tui-ge-de-zi-fu-chuan-by-leetcode-solu/
方法一:重构字符串:借助了额外的空间
思路及算法
最容易想到的方法是将给定的字符串中的退格符和应当被删除的字符都去除,还原给定字符串的一般形式。然后直接比较两字符串是否相等即可。
具体地,我们用栈处理遍历过程,每次我们遍历到一个字符:
如果它是退格符,那么我们将栈顶弹出;
如果它是普通字符,那么我们将其压入栈中。
代码:
C++版本: bool backspaceCompare(string S, string T) { return build(S) == build(T); } string build(string str) { string ret; for (char ch : str) {//遍历str中的每个字符 if (ch != '#') { ret.push_back(ch);//压栈 } else if (!ret.empty()) { ret.pop_back();//出栈 } } return ret; }
复杂度分析
时间复杂度:O(N+M),其中 N 和 M 分别为字符串 S 和 T 的长度。我们需要遍历两字符串各一次。
空间复杂度:O(N+M),其中 N 和 M 分别为字符串 S 和 T 的长度。主要为还原出的字符串的开销。
方法二:双指针
思路及算法
一个字符是否会被删掉,只取决于该字符后面的退格符,而与该字符前面的退格符无关。因此当我们逆序地遍历字符串,就可以立即确定当前字符是否会被删掉。
具体地,我们定义skip 表示当前待删除的字符的数量。每次我们遍历到一个字符:
若该字符为退格符,则我们需要多删除一个普通字符,我们让 skip 加 1;
若该字符为普通字符:
若skip 为 0,则说明当前字符不需要删去;
若skip 不为 0,则说明当前字符需要删去,我们让skip 减 1。
这样,我们定义两个指针,分别指向两字符串的末尾。每次我们让两指针逆序地遍历两字符串,直到两字符串能够各自确定一个字符,然后将这两个字符进行比较。重复这一过程直到找到的两个字符不相等,或遍历完字符串为止。
C++版本: bool backspaceCompare(string S, string T) { int i = S.length() - 1, j = T.length() - 1; int skipS = 0, skipT = 0; while (i >= 0 || j >= 0) { while (i >= 0) { if (S[i] == '#') { skipS++, i--; } else if (skipS > 0) { skipS--, i--; } else { break; } } 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; }
复杂度分析
时间复杂度:O(N+M),其中 N 和 M 分别为字符串 S 和 T 的长度。我们需要遍历两字符串各一次。
空间复杂度:O(1)。对于每个字符串,我们只需要定义一个指针和一个计数器即可。