用于检查带有退格符的字符串是不是相等的节省空间的算法?

Posted

技术标签:

【中文标题】用于检查带有退格符的字符串是不是相等的节省空间的算法?【英文标题】:Space-efficient algorithm for checking if strings with backspaces are equal?用于检查带有退格符的字符串是否相等的节省空间的算法? 【发布时间】:2019-10-30 02:02:08 【问题描述】:

我最近在一次采访中被问到这个问题:

给定两个字符串 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) 空间复杂度中解决它吗?

注意:我们也可以有多个退格字符。

【问题讨论】:

您要查找# 还是退格字符? 看我上面问题中的例子,你就明白了。这是一个退格字符。 我想正则表达式可以删除紧接在#之前的任何字符 您根本不需要任何额外的存储空间来执行此操作。只有两个原始字符串。 Scala String Equality Question from Programming Interview的可能重复 【参考方案1】:

为了达到O(1)的空间复杂度,使用两个指针并从字符串的末尾开始:

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 &gt; 0s.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).

Source 1, Source 2.

【讨论】:

你知道这个的时间复杂度吗?我的直觉是,虽然现在有两个循环,但它仍然受退格数的限制,而退格数又受字符串的组合长度(即线性)的限制。 @Thilo 你是对的!时间复杂度为O(n):外部while循环只是不时将责任传递给内部循环。 sol("", "a") 将在此代码中返回 true。也许可以接受采访。不适合正确的解决方案。【参考方案2】:

修正了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

【讨论】:

以上是关于用于检查带有退格符的字符串是不是相等的节省空间的算法?的主要内容,如果未能解决你的问题,请参考以下文章

SQLSERVER NULL和空字符串的区别 使用NULL是不是节省空间

检查两个排序的字符串在 O(log n) 时间内是不是相等

== 检查布尔值是不是完全相等? - 爪哇

检查两个文件是不是相等的最快哈希算法是啥?

vb 检查 2 个字符串是不是有 2 个不相等的字符

检查两个“选择”是不是相等