JZ28 对称的二叉树
(中等)
题目
思路
可采用层序遍历来解决这道题,我的第一想法就是用队列每次存储一层的结点值,然后判断这个序列是否对称即可,也满足空间复杂度为 O(1)常数阶,当然,也可采用递归来解决这道题目,我就是选择的后者,因为我一直感觉我的递归不是很熟练。
我在解决这道题目时,将根结点单独作为一种情况的判断,将其子结点按另一大类情况来判断,但后来又看了一下官方的题解,意识到这两种情况可以合为一种情况,从而简化代码。
递归过程中,传入的参数为两个欲判断是否对称的结点(当然,由于根结点的判断也与后续结点的判断归一化,因此根结点这种情况传两次它的自身引用即可),两结点分三种情况讨论:都为空、一个为空、都不为空
- 两结点都为空:这种子情况是对称的,返回
true
- 两结点一个为空:一定不对称,返回
false
- 两结点都不为空:要进一步判断是否对称,并且其各自的子结点情况是否对称
实现
public class JZ28对称的二叉树 {
boolean isSymmetrical(TreeNode pRoot) {
return isMirror(pRoot, pRoot);
}
private boolean isMirror(TreeNode node1, TreeNode node2) {
//两结点分三种情况:都为空、一个为空、都不为空
//两结点都为空
if (node1 == null && node2 == null) return true;
//两结点一个为空
if (node1 == null || node2 == null) return false;
//两结点都不为空
return (node1.val == node2.val) &&
isMirror(node1.left, node2.right) &&
isMirror(node1.right, node2.left);
}
}
JZ37 序列化二叉树
(较难)
题目
思路
本题分为两问,第一问是将二叉树序列化为字符串,第二问是将字符串反序列化为二叉树。可采用前、中、后、层序遍历来解决,这里,我才用前序遍历来解决,思路大体相同,都是在遍历时生成字符串或生成树。
将二叉树序列化为字符串:可采用递归遍历来实现,这里我采用前序遍历来得出存储各结点值的字符串,各值之间使用英文分号(;)隔开,对于递归时遇到的空结点,用井号(#)表示空结点的值,前序遍历很基础,这里就不再说了。
将字符串反序列化为二叉树:由于此字符串中的值对应二叉树的前序遍历顺序,因此,在反序列化时,也要在递归时进行前序构造二叉树,递归为了方便考虑,可将此字符串中的值以之前分隔符为标识,存储到一个链表中,这样,每次的递归方法栈,以此链表的引用为参数,使得所有的递归都有着统一的生产者源(也就是那个链表),这样,就不必再去考虑用下标索引或是说成员变量式的下标索引来进行字符串中、递归之中下标索引的定位了,从而用前序的构造方式逐步取出链表中的结点值,进而生成新的树结点并插入到相应位置。
关于递归,我一直认为用文字表述不如之间看代码更易懂,因此更建议直接看代码,思路部分只是我自己的一种反思方式。
实现
public class JZ37序列化二叉树 {
String Serialize(TreeNode root) {
if (root == null) return "#;";
return root.val + ";" + Serialize(root.left) + Serialize(root.right);
}
TreeNode Deserialize(String str) {
String[] split = str.split(";");
LinkedList<String> list = new LinkedList();
for (int i = 0; i < split.length; i++) {
list.add(split[i]);
}
return toTree(list);
}
TreeNode toTree(LinkedList<String> list) {
String value = list.poll();
if (value.equals("#")) {
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(value));
root.left = toTree(list);
root.right = toTree(list);
return root;
}
}