LeetCode 606. Construct String from Binary Tree

Given the root of a binary tree, construct a string consisting of parenthesis and integers from a binary tree with the preorder traversal way, and return it.

Omit all the empty parenthesis pairs that do not affect the one-to-one mapping relationship between the string and the original binary tree.

Example 1:

Input: root = [1,2,3,4]
Output: "1(2(4))(3)"
Explanation: Originally, it needs to be "1(2(4)())(3()())", but you need to omit all the unnecessary empty parenthesis pairs. And it will be "1(2(4))(3)"

Example 2:

Input: root = [1,2,3,null,4]
Output: "1(2()(4))(3)"
Explanation: Almost the same as the first example, except we cannot omit the first parenthesis pair to break the one-to-one mapping relationship between the input and the output.

Constraints:

  • The number of nodes in the tree is in the range [1, 104].
  • -1000 <= Node.val <= 1000

本质就是preorder,只是在打印每个node的时候,把它的child都放进括号里。如果是有left没有right就不用给right一个空括号;但如果有right没有left就要给left一个空括号占个位置。

递归的写法还挺容易

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public String tree2str(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        preorder(root, sb);
        return sb.toString();
    }

    private void preorder(TreeNode root, StringBuilder sb) {
        sb.append(root.val);
        if (root.left != null) {
            sb.append("(");
            preorder(root.left, sb);
            sb.append(")");
        }
        if (root.right != null) {
            if (root.left == null) {
                sb.append("()");
            } 
            sb.append("(");
            preorder(root.right, sb);
            sb.append(")");
        }
    }
}

迭代,不小心提前被剧透了需要用到额外set,就自己写了个80%。然而没想到的点就是可以每次在sb.append(node.va)的时候按"(" + node.val来append,而不用node.val + "(",这样就无脑很多,不需要考虑那么多情况,最后return的时候substring一下就完事了。

其实跟preorder的迭代一样,但是需要用到额外的seen set来判断这个node是否已经遍历过了,这个其实很容易想到,因为要给string加后括号相当于是要有回溯的思想在里面。自己写的时候因为是边想边写的,所以把有没有左右的情况分的很清楚,其实可以更优化的:我们只需要考虑在node被peek的时候无脑"(" + node.val,被pop的时候无脑")",其他时候就只有当left == null && right != null的时候加个"()"就行了。

自己写的:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public String tree2str(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        Deque<TreeNode> stack = new ArrayDeque<>();
        Set<TreeNode> seen = new HashSet<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.peek();
            if (!seen.contains(node)) {
                sb.append("(" + node.val);
                seen.add(node);
                if (node.left != null && node.right != null) {
                    stack.push(node.right);
                    stack.push(node.left);
                } else if (node.left == null && node.right == null) {
                    sb.append(")");
                } else if (node.left == null && node.right != null) {
                    sb.append("()");
                    stack.push(node.right);
                } else {
                    stack.push(node.left);
                }
            } else {
                node = stack.pop();
                if (node.left != null || node.right != null) {
                    sb.append(")");
                }
            }
        }
        return sb.substring(1, sb.length() - 1).toString();
    }
}

优化版,其实不仅代码简洁,速度也快了不少。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public String tree2str(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        Deque<TreeNode> stack = new ArrayDeque<>();
        Set<TreeNode> seen = new HashSet<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.peek();
            if (!seen.contains(node)) {
                sb.append("(" + node.val);
                seen.add(node);
                if (node.right != null && node.left == null) {
                    sb.append("()");
                }
                if (node.right != null) {
                    stack.push(node.right);
                }
                if (node.left != null) {
                    stack.push(node.left);
                }
            } else {
                node = stack.pop();
                sb.append(")");
            }
        }
        return sb.substring(1, sb.length() - 1).toString();
    }
}

然后还看到了一种不需要用visited set的,采用dummy node。因为一个前括号总会搭配一个后括号,并且后括号应该在遍历完左右子树以后才出现,于是我们可以每次pop一个node的时候就先push一个dummy node。如果pop到的是dummy node就给它加个后括号。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public String tree2str(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        Deque<TreeNode> stack = new ArrayDeque<>();
        TreeNode dummy = new TreeNode();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            if (node == dummy) {
                sb.append(")");
            } else {
                sb.append("(" + node.val);
                stack.push(dummy);
                if (node.right != null && node.left == null) {
                    sb.append("()");
                }
                if (node.right != null) {
                    stack.push(node.right);
                }
                if (node.left != null) {
                    stack.push(node.left);
                }
            }
        }
        return sb.substring(1, sb.length() - 1).toString();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值