【问题标题】:Need help constructing string with parenthesis from Binary Tree需要帮助从二叉树构造带括号的字符串
【发布时间】:2020-08-27 14:09:07
【问题描述】:

我正在尝试解决以下算法问题:

你需要用前序遍历的方式从二叉树中构造一个由括号和整数组成的字符串。

空节点需要用空括号对“()”表示。并且需要省略所有不影响字符串与原二叉树一一映射关系的空括号对。

示例 1: 输入:二叉树:[1,2,3,4]

       1
     /   \
    2     3
   /
  4

输出:“1(2(4))(3)”

解释:原来需要是“1(2(4)())(3()())”, 但是您需要省略所有不必要的空括号对。 它将是“1(2(4))(3)”。

示例 2: 输入:二叉树:[1,2,3,null,4]

       1
     /   \
    2     3
     \
      4

输出:“1(2()(4))(3)”

解释:和第一个例子差不多, 除了我们不能省略第一个括号对来打破输入和输出之间的一对一映射关系。

我写了以下代码:

class TreeNode {
    constructor(val, left, right) {
        this.val = (val === undefined ? 0 : val)
        this.left = (left === undefined ? null : left)
        this.right = (right === undefined ? null : right)
    }
}

const tree2str = (t) => {
    const result = []
    const stack = []

    const dfs = (current) => {
        if (current === null) return
        result.push(current.val)
        if (!current.left && current.right) result.push('(')
        if (current.left) {
            result.push('(')
            stack.push(')')
            dfs(current.left)
        }
        while (stack.length) {
            result.push(stack.pop())
        }
        if (!current.left && current.right) stack.push(')')
        if (current.right) {
            result.push('(')
            stack.push(')')
            dfs(current.right)
        }
    }
    dfs(t)
    return result.join('')
}

到目前为止我的测试用例:

const tree = new TreeNode(1, new TreeNode(2, new TreeNode(4)), new TreeNode(3))
const tree2 = new TreeNode(1, new TreeNode(2, null, new TreeNode(4)), new TreeNode(3))
const tree3 = new TreeNode(1, new TreeNode(2, new TreeNode(3), new TreeNode(4)))

console.log(tree2str(tree)) // "1(2(4)())(3()())" ==> "1(2(4))(3)"
console.log(tree2str(tree2)) // "1(2()(4))(3)"
console.log(tree2str(tree3)) // "1(2(3)(4))" instead got "1(2(3))(4)"

只有两个工作,然而,我在第三个工作中遇到了问题,并且无法发现我哪里出错了。

【问题讨论】:

  • 为什么必须用while (stack.length) 清空整个堆栈?也就是说,你为什么需要stackreturn val + "(" + recurse(left) + ")(" + recurse(right + ")";

标签: javascript arrays stack binary-tree depth-first-search


【解决方案1】:

堆栈使事情变得更加复杂。错误是最终你会在最后一个测试用例中弹出堆栈两次,这会弄乱开闭括号。我删除了堆栈并使代码更易于调试。但是,我使用了双栈方法来解释算术表达式,但这似乎没有必要。

您可以在此沙盒中试用代码:https://codesandbox.io/s/need-help-constructing-string-with-parenthesis-from-binary-tree-p3sk3?file=/src/index.js

const tree2str = t => {
  const result = [];
  const dfs = current => {
    if (!current) {
      return;
    }

    const { val, left, right } = current;
    if (val !== null && val !== undefined) {
      result.push(val);
      if (left) {
        result.push("(");
        dfs(left);
        result.push(")");
      } else if (!left && right) {
        result.push("()");
      }

      if (right) {
        result.push("(");
        dfs(right);
        result.push(")");
      }
    }
  };
  dfs(t);
  return result.join("");
};

这个版本似乎产生了您正在寻找的结果。不过这很有趣!

【讨论】:

  • 我将此行添加为第一行if (t && !t.left && !t.right) return ${t.val}作为保护条件;但是,还有另一个测试用例没有通过。输入是[0,0,0,0,null,null,0,null,null,null,0],应该返回"0(0(0))(0()(0()(0)))"。我有点不知所措,因为它只返回""。关于如何合并此测试以通过的任何想法?
  • 另外,任何人都可以共享迭代解决方案。我尝试使用堆栈,但无法解决逻辑问题。
  • 我做了一个可能有效的小改动。如果 val 为零,if(val) 行将评估为 false。因此,如果您传入零,它现在应该评估其余代码。
  • 为什么使用数组而不是字符串?因为这个答案对我来说感觉像是一个不必要的过于复杂的解决方案。有一些硬编码的条件,还有很多可以简化的数据会占用内存。
  • OP 需要帮助解决问题,而不是完全重写。
【解决方案2】:

正如用户@Jonas Wilms 所提到的,我认为不需要使用堆栈来解决这个问题。我个人觉得使用递归方法更为常见(我认为它更有效/更易读)。

这是代码

class TreeNode {
    constructor(val, left, right) {
        this.val = (val === undefined ? 0 : val)
        this.left = (left === undefined ? null : left)
        this.right = (right === undefined ? null : right)
    }
}

const tree2str = (tree) => {

    const dfs = (current) => {
        if (current === null) return ''

        let result = current.val.toString(); // in fact you don't need toString() here, but has a better readability

        const left = current.left;
        const right = current.right;

        if (left || right) {
            result += '(' + dfs(left) + ')';
        } 
        if (right) {
            result += '(' + dfs(right) + ')';
        }
        return result
    }
    return dfs(tree);
}

const tree1 = new TreeNode(1, new TreeNode(2, new TreeNode(4)), new TreeNode(3))
const tree2 = new TreeNode(1, new TreeNode(2, null, new TreeNode(4)), new TreeNode(3))
const tree3 = new TreeNode(1, new TreeNode(2, new TreeNode(3), new TreeNode(4)))

console.log(tree2str(tree1)) // "1(2(4))(3)"
console.log(tree2str(tree2)) // "1(2()(4))(3)"
console.log(tree2str(tree3)) // "1(2(3)(4))"

我试图让代码尽可能简单,而且我很确定有办法改进这一点。如果任何其他输入测试不起作用,请发表评论。这是一个很好的挑战。干杯:)

【讨论】:

    猜你喜欢
    • 2020-08-03
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 2015-02-11
    相关资源
    最近更新 更多