17.树的子结构
题目:
输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构) B是A的子结构, 即 A中有出现和B相同的结构和节点值。
题解:
recur
函数,递归判断两个子树是否相等
- 递归结束的条件
- B为null,因为null为任意一个树的子结构,返回true;
- 如果A为null则说明B比A多,返回false;
- 如果A和B的val不相等,返回false。
- 如果A和B未达到结束的条件,则递归的调用recur函数分别判断左右子树是否相等。
isSubStructure
函数,判断是否是子树
- 如果A或B为null,则返回false;
- 调用recur函数判断A和B是否相等,递归调用isSubStructure函数判断B是否为A.left的子树,B是否为A.right的子树。
public boolean isSubStructure(TreeNode A, TreeNode B) {
if (A == null || B == null) return false;
return recur(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B);
}
boolean recur(TreeNode A, TreeNode B) {
if (B == null) return true;
if (A == null || A.val != B.val) return false;
return recur(A.left,B.left) && recur(A.right,B.right);
}
18.二叉树的镜像
题目:
请完成一个函数,输入一个二叉树,该函数输出它的镜像。
题解:
swap
函数递归交换每个节点的左右节点
- 递归结束的条件
- A和B均为null,说明root为叶子节点,不需要继续向下交换左右节点,递归结束;
- 如果未达到递归结束的条件
- 利用中间节点temp实现root左右节点的交换;
- 如果左子树不为null,则递归交换其左右节点;
- 如果右子树不为null,则递归交换其左右节点。
public TreeNode mirrorTree(TreeNode root) {
if (root == null) return null;
TreeNode res = root;
swap(root,root.left,root.right);
return res;
}
void swap(TreeNode root,TreeNode A, TreeNode B){
if (A == null && B == null) return;
TreeNode temp;temp = A;
root.left = root.right;
root.right = temp;
if (A != null) swap(A,A.left,A.right);
if (B != null) swap(B,B.left,B.right);
}
19.对称的二叉树
题目:
请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是对称的。
题解一:
- 使用
mirrorTree
函数获得二叉树的镜像; - 使用
isEqual
函数判断镜像和原二叉树是否相同; - 由于mirrorTree函数的具体实现是在原二叉树的基础上交换左右节点,因此需要
copy
函数获得二叉树的副本
mirrorTree 函数
- 详情见 [18.二叉树的镜像]
isEqual 函数
- 递归结束的条件
- A为空&&B不为空 或者 A不为空&&B为空,返回false;
- 二者均为null,返回true;
- 若二者均不为null,且A.val != B.val ,返回false。
- 未满足递归结束的条件
- 即二者均不为null,且A.val == B.val;
- 此时递归的调用
isEqual
函数,判断A的左子树和B的左子树是否相同、A的右子树和B的右子树是否相同
copy 函数
- 应用深度拷贝的思想;
- 首先通过queue遍历二叉树的所有节点,并创建与其相对应的节点,将二者存入map中;
- 二次遍历二叉树,设置新节点的左右节点。
public TreeNode mirrorTree(TreeNode root) {
if (root == null) return null;
TreeNode res = root;
swap(root,root.left,root.right);
return res;
}
void swap(TreeNode root,TreeNode A, TreeNode B){
if (A == null && B == null) return;
TreeNode temp;temp = A;
root.left = root.right;
root.right = temp;
if (A != null) swap(A,A.left,A.right);
if (B != null) swap(B,B.left,B.right);
}
public boolean isSymmetric(TreeNode root) {
TreeNode tempRoot = copy(root);
TreeNode mirror = mirrorTree(root);
return isEqual(tempRoot,mirror);
}
public boolean isEqual(TreeNode A,TreeNode B) {
if ((A == null && B != null) || (A != null && B == null )) return false;
if (A == null && B == null) return true;
if (A.val != B.val) return false;
return isEqual(A.left,B.left) && isEqual(A.right,B.right);
}
TreeNode copy(TreeNode root){
if (root == null) return null;
Queue<TreeNode> queue = new LinkedList<TreeNode>(){{add(root);}};
Map<TreeNode,TreeNode> map = new HashMap<>();
while (!queue.isEmpty()){
TreeNode remove = queue.remove();
TreeNode treeNode = new TreeNode(remove.val);
map.put(remove,treeNode);
if (remove.left != null) queue.add(remove.left);
if (remove.right != null) queue.add(remove.right);
}
queue.add(root);
while (!queue.isEmpty()){
TreeNode poll = queue.poll();
map.get(poll).left = map.get(poll.left);
map.get(poll).right = map.get(poll.right);
if (poll.left != null) queue.add(poll.left);
if (poll.right != null) queue.add(poll.right);
}
return map.get(root);
}
题解二:
- 若节点L和节点R对称,则应该满足L.left和R.right对称,L.right和R.left对称;
isSymmetric 函数
- 如果root为null,返回true;
- 调用recur函数,判断root的左右子树是否对称。
recur 函数
- 递归结束的条件
- L和R均为null,则二者必然对称,返回true;
- 若L为null(此时R不为null)、R为null(此时L为null)、L和R的val不同(此时L和R均不为null)时,二者不对称,返回false;
- 未满足递归结束的条件
- 即L和R均不为null,且L.val == R.val;
- 此时递归调用recur函数判断L.left和R.right是否对称,L.right和R.left是否对称。
public boolean isSymmetric(TreeNode root) {
if (root == null) return true;
return recur(root.left,root.right);
}
boolean recur(TreeNode L, TreeNode R) {
if(L == null && R == null) return true;
if(L == null || R == null || L.val != R.val) return false;
return recur(L.left, R.right) && recur(L.right, R.left);
}
在我们这个星球上,每天都要发生许多变化,有人倒霉了;有人走运了;有人在创造历史,历史也在成全或抛弃某些人。