代码之家  ›  专栏  ›  技术社区  ›  flash

检查带退格字符串是否相等的节省空间算法?

  •  4
  • flash  · 技术社区  · 7 年前

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

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

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

    0 回复  |  直到 7 年前
        1
  •  12
  •   Oleksandr Pyrohov Andreas    7 年前

    为了实现 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 > 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) .

    Source 1 , Source 2 .

        2
  •  2
  •   ciamej    7 年前

    已更正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