Javascript 需要帮助从二叉树构造带括号的字符串吗

Javascript 需要帮助从二叉树构造带括号的字符串吗,javascript,arrays,stack,binary-tree,depth-first-search,Javascript,Arrays,Stack,Binary Tree,Depth First Search,我试图解决以下算法问题: 您需要使用前序遍历方式从二叉树构造一个由括号和整数组成的字符串 空节点需要用空括号对“()”表示。您需要省略所有不影响字符串和原始二叉树之间一对一映射关系的空括号对 例1: 输入:二叉树:[1,2,3,4] 1 / \ 2 3 / 4 输出:“1(2(4))(3)” 说明:最初它需要是“1(2(4)()(3)()”, 但是您需要省略所有不必要的空括号对。 这将是“1(2(4))(3)” 例2: 输入:二叉树:[1,

我试图解决以下算法问题:

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

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

例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)"

但是,只有两个工作,我在处理第三个工作时遇到了问题,无法发现哪里出了问题。

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

您可以在此沙箱中试用代码:


这个版本似乎能产生你想要的结果。不过那很有趣

正如user@Jonas Wilms提到的,我认为没有必要使用stack来解决这个问题。我个人觉得使用递归方法更常见(我认为它更有效/可读)

这是密码

类树节点{
构造函数(val、左、右){
this.val=(val==未定义?0:val)
this.left=(left==未定义?null:左)
this.right=(right==未定义?null:右侧)
}
}
常量tree2str=(树)=>{
常量dfs=(当前)=>{
如果(当前===null)返回“”
让result=current.val.toString();//实际上,这里不需要toString(),但具有更好的可读性
const left=current.left;
const right=current.right;
如果(左| |右){
结果+='('+dfs(左)+');
} 
如果(右){
结果+='('+dfs(右)+');
}
返回结果
}
返回dfs(树);
}
常数树1=新树节点(1,新树节点(2,新树节点(4)),新树节点(3))
const tree2=新树节点(1,新树节点(2,null,新树节点(4)),新树节点(3))
常数tree3=新TreeNode(1,新TreeNode(2,新TreeNode(3),新TreeNode(4)))
控制台日志(tree2str(tree1))/“1(2(4))(3)”
console.log(tree2str(tree2))/“1(2()(4))(3)”

console.log(tree2str(tree3))/“1(2(3)(4))”
为什么在(stack.length)时必须用
清空整个堆栈?也就是说,为什么您需要
堆栈
returnval+”(“+recurse(left)+”(+recurse(right+”)”);
I添加这一行作为第一行
if(t&&!t.left&&!t.right)return${t.val}
作为保护条件;但是,还有另一个测试用例没有通过。输入是
[0,0,0,null,null,0,null,0]
,应该返回
“0(0(0))(0)(0()(0))“
。我有点不知所措,因为它只返回
。关于如何合并此测试以通过测试,有什么想法吗?还有,是否有人能够共享一个迭代解决方案。我尝试使用堆栈,但无法解决逻辑上的问题。我做了一个可能有效的小更改。
if(val)
如果val为零,line的计算结果将为false。因此,如果传入零,那么现在它应该计算代码的其余部分。为什么使用数组而不是字符串?因为我觉得这是一个不必要的过于复杂的解决方案。有一些硬编码的条件,以及许多可以简化的数据,这些数据占用了内存OP需要帮助解决问题,而不是完全重写。
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("");
};