leetcode
leetcode 451 ~ 500
从字符串生成二叉树

从字符串生成二叉树

难度:

标签:

题目描述

代码结果

运行时间: 48 ms, 内存: 17.3 MB


/*
题目思路:
1. 使用递归方法将字符串解析为二叉树。
2. 使用Stream API来处理字符串并构建二叉树。
3. 使用栈来跟踪节点和它们的位置。
*/
 
import java.util.stream.*;
import java.util.*;
 
public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
 
public class Solution {
    public TreeNode str2tree(String s) {
        if (s == null || s.length() == 0) {
            return null;
        }
        return helper(s.chars().toArray(), new int[1]);
    }
 
    private TreeNode helper(int[] s, int[] index) {
        if (index[0] >= s.length) {
            return null;
        }
        boolean negative = false;
        if (s[index[0]] == '-') {
            negative = true;
            index[0]++;
        }
        int num = 0;
        while (index[0] < s.length && Character.isDigit(s[index[0]])) {
            num = num * 10 + (s[index[0]] - '0');
            index[0]++;
        }
        if (negative) {
            num = -num;
        }
        TreeNode root = new TreeNode(num);
        if (index[0] < s.length && s[index[0]] == '(') {
            index[0]++;
            root.left = helper(s, index);
            index[0]++;
        }
        if (index[0] < s.length && s[index[0]] == '(') {
            index[0]++;
            root.right = helper(s, index);
            index[0]++;
        }
        return root;
    }
}
 

解释

方法:

这个题解的思路是使用一个栈来模拟递归构建二叉树的过程。遍历字符串 s,遇到数字则累计存储,遇到左括号则根据累计的数字生成一个新节点,并将其加入栈中。如果栈顶节点的左子节点为空则将新节点作为左子节点,否则作为右子节点。遇到右括号则弹出栈顶节点。最后栈底元素即为构建出的二叉树的根节点。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在遍历过程中,如何确保每个数字都能正确地累积,尤其是考虑到可能存在多位数的情况?
在代码中,遍历字符串时使用一个变量`num`来累计每个字符。如果遇到的字符是数字(即不是左或右括号),则将该字符追加到`num`字符串的末尾。这样,遇到非数字字符时(左括号或右括号),`num`中存储的是完整的数字字符串,可以一次性转换为整数。此方法确保了即使是多位数也能被正确累积和转换。
🦆
函数`generate_node`是在遇到每一个括号时调用的,那么如果字符串以数字结尾而非括号,这种情况下`generate_node`应该如何处理?
在题解的实现中,如果字符串以数字结尾,`generate_node`并未在循环结束后显式调用。这可能会导致最后一个数字节点没有被创建。为了解决这个问题,可以在循环结束后检查`num`是否非空,如果非空,则需要调用`generate_node`来生成最后一个节点。这确保了所有的数字都能被转换为树节点,即使是在字符串的末尾。
🦆
在处理右括号`)`时,直接弹出栈顶元素似乎忽略了检查这个节点是否已经正确连入其父节点的左右子树中,这样做是否安全?
在题解的逻辑中,遇到右括号时弹出栈顶元素是安全的。这是因为在之前的逻辑中,每当生成一个新的节点并且栈中已有其他节点时,新节点会被加入到栈顶节点的左或右子节点中。因此,当遇到一个右括号时,表示当前节点的所有子节点都已经处理完毕,可以安全地从栈中移除。
🦆
题解中提到,如果栈顶节点的左子节点为空则新节点作为左子节点,否则作为右子节点。如果栈顶节点左右子节点都不为空该如何处理?
在当前题解的实现逻辑中,每个节点入栈时其左右子节点都是空的。新节点作为左子节点或右子节点的决定是在节点第一次加入栈时进行的。一旦一个节点的左右子节点都被赋值,它就会在遇到下一个右括号时被弹出栈。因此,不会出现栈顶节点左右子节点都不为空的情况,因为这样的节点不会再次遇到新节点需要连接的情况。

相关问题

根据二叉树创建字符串

给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。

空节点使用一对空括号对 "()" 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

 

示例 1:

输入:root = [1,2,3,4]
输出:"1(2(4))(3)"
解释:初步转化后得到 "1(2(4)())(3()())" ,但省略所有不必要的空括号对后,字符串应该是"1(2(4))(3)" 。

示例 2:

输入:root = [1,2,3,null,4]
输出:"1(2()(4))(3)"
解释:和第一个示例类似,但是无法省略第一个空括号对,否则会破坏输入与输出一一映射的关系。

 

提示:

  • 树中节点的数目范围是 [1, 104]
  • -1000 <= Node.val <= 1000