代码改变世界

剑指offer面试题18-树的子结构

2017-06-10 14:21  tlnshuju  阅读(178)  评论(0编辑  收藏  举报

题目:

输入两颗二叉树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);
	}
}