题目地址:
https://leetcode.com/problems/construct-string-from-binary-tree/
以先序遍历,用括号的方式序列化一棵二叉树。”用括号的方式“的意思是,首先序列化的字符串以树根开头,接着递归序列化左子树并且在外面套一层括号后append在后面,然后递归序列化右子树并且在外面套一层括号后append在后面。此处为了节省空间,当右子树为空时,序列化右子树时外层括号需要去掉;如果左右子树都为空时,则序列化左右子树时外层括号都要去掉;但是如果只是左子树为空,右子树不为空时,左子树对应的括号不能去掉(否则反序列化时无法区分是左子树还是右子树)。
思路是递归。如果树空则直接返回;如果是叶子节点,则直接append叶子然后返回(因为此时左右子树都为空,括号是不能加的);否则,先将树根append上去,接着append左括号,递归序列化左子树,然后append上右括号(这里不需要判断左子树是否非空,因为即使是空树也要把空括号加上去),接着,判断一下右子树是否非空,如果非空,再append左括号,递归序列化右子树再append右括号(这里是需要判断右子树是否非空的,如果是空树,按照约定,就不用加括号了)。代码如下:
public class Solution {
public String tree2str(TreeNode root) {
if (root == null) {
return "";
}
StringBuilder sb = new StringBuilder();
dfs(root, sb);
return sb.toString();
}
private void dfs(TreeNode root, StringBuilder sb) {
if (root == null) {
return;
}
// 是叶子节点时,左右子树的空括号都不需要加,直接返回
if (root.left == null && root.right == null) {
sb.append(root.val);
return;
}
// 如果root不是叶子,那么无论左子树是否空,都需要把左子树的那个括号加上
sb.append(root.val).append('(');
dfs(root.left, sb);
sb.append(')');
if (root.right != null) {
sb.append('(');
dfs(root.right, sb);
sb.append(')');
}
}
}
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) {
val = x;
}
}
时空复杂度 O ( n ) O(n) O(n)。
关于反序列化的唯一性,可以由数学归纳法证明。