题目:
输入两颗二叉树A和B,判断B是不是A的子结构。
树的结构如下:
package com.aii.algorithm;
public class TreeNode {
int value;
TreeNode left;
TreeNode right;
public TreeNode(int value) {
this.value = value;
}
}
全在注释上:
package com.aii.algorithm;
public class HasSubTree {
// 分两步:
// 1.遍历
// 2.对于遍历到的节点与sub的根节点相同的,再仔细比较
public boolean check(TreeNode root, TreeNode sub) {
// 当前空,则返回false,表示遍历完了,都没找到。
if (root == null) {
return false;
}
TreeNode current = root;
// 先序遍历,先判断自己再说
if (current == sub) {
// 如果是相同的,那就比较,
// 如果比较成功,那就返回true,
// 如果比较失败,也不能返回false,因为有可能这里不匹配剩下的有匹配的
// 所有是用if(boolean)return true而不用return boolean.
if (checkThis(current, sub)) {
return true;
}
}
// 先序遍历到了左边。因为root为空的时候,则返回false
// 而左没了还有右,所以不能直接check(root.left,sub)
// 如果左没了,就找右,如果左有,就找找看
if (root.left != null) {
if (check(root.left, sub)) {
return true;
}
}
// 最后到了右,不管怎么样
// 既然都到这了,说明中,左都没找到
// 所以可以直接return check(root.right,sub);
return check(root.right, sub);
}
// 此方法用来判断当前的current节点是否包含sub节点,而且是一一对应的
// 即current=sub;
// current.left=sub.left;
// current.right=sub.right;
private boolean checkThis(TreeNode current, TreeNode sub) {
// sub为null,说明遍历完了,没找到不符合的,返回true
if (sub == null) {
return true;
}
// 这里也是采用递归遍历,先序遍历的方法
// 万一遇到一个不同的,返回false
if (sub != current) {
return false;
}
// 左边,与前面不同的是,先判断左边是不是有不同的,有就肯定是false,
// 没有也不代表是肯定相同,还得看右边
if (sub.left != null) {
if (!checkThis(current.left, sub.left)) {
return false;
}
}
// 最后右边
return checkThis(current.right, sub.right);
}
}