私は最近、インタビューでこの質問をされました:
2つの文字列sとtが与えられ、両方が空のテキストエディターに入力されたときにそれらが等しい場合に返します。 #はバックスペース文字を意味します。
Input: S = "ab#c", T = "ad#c"
Output: true
Explanation: Both S and T become "ac".
私は以下の解決策を思いつきましたが、スペース効率が良くありません:
public static boolean sol(String s, String t) {
return helper(s).equals(helper(t));
}
public static String helper(String s) {
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c != '#')
stack.Push(c);
else if (!stack.empty())
stack.pop();
}
return String.valueOf(stack);
}
スタックを使用しないこの問題を解決するためのより良い方法があるかどうかを確認したかったのです。つまり、O(1)空間の複雑さで解決できますか?
注:複数のバックスペース文字を含めることもできます。
O(1)
スペースの複雑さを実現するには、Two Pointersを使用して、文字列の最後から開始します。
_public static boolean sol(String s, String t) {
int i = s.length() - 1;
int j = t.length() - 1;
while (i >= 0 || j >= 0) {
i = consume(s, i);
j = consume(t, j);
if (i >= 0 && j >= 0 && s.charAt(i) == t.charAt(j)) {
i--;
j--;
} else {
return i == -1 && j == -1;
}
}
return true;
}
_
主な考え方は、_#
_カウンターを維持することです。文字が_#
_の場合はcnt
をインクリメントし、そうでない場合はデクリメントします。そして、_cnt > 0
_およびs.charAt(pos) != '#'
の場合-文字をスキップします(デクリメント位置):
_private static int consume(String s, int pos) {
int cnt = 0;
while (pos >= 0 && (s.charAt(pos) == '#' || cnt > 0)) {
cnt += (s.charAt(pos) == '#') ? +1 : -1;
pos--;
}
return pos;
}
_
時間の複雑さ:O(n)
。
Templatetypedefの疑似コードを修正
// Index of next spot to read from each string
let sIndex = s.length() - 1
let tIndex = t.length() - 1
let sSkip = 0
let tSkip = 0
while sIndex >= 0 and tIndex >= 0:
if s[sIndex] = #:
sIndex = sIndex - 1
sSkip = sSkip + 1
continue
else if sSkip > 0
sIndex = sIndex - 1
sSkip = sSkip - 1
continue
// Do the same thing for t.
if t[tIndex] = #:
tIndex = tIndex - 1
tSkip = tSkip + 1
continue
else if tSkip > 0
tIndex = tIndex - 1
tSkip = tSkip - 1
continue
// Compare characters.
if s[sIndex] != t[tIndex], return false
// Back up to the next character
sIndex = sIndex - 1
tIndex = tIndex - 1
// The strings match if we’ve exhausted all characters.
return sIndex < 0 and tIndex < 0