《剑指offer》——树的子结构

60 篇文章 3 订阅

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

T:

题目描述
输入两颗二叉树A,B,判断B是不是A的子结构。

这地方需要注意的有两点:

  1. 判断的是**“子结构”,而非“子树”**,我第一次提交,就当成子树去做的,结果error;
  2. 如果两个子树中有一个是null,那么就返回false,这个规定题目中没有给出说明,《剑指offer》中的很多题目都有类似的缺陷。

这种题目,递归是最好的方式,我的思路:

略微麻烦了些,因为是将B和A比较,判断B是否是A的子结构,那就以A为出发点,将A的所有节点都放在一个队列里面,然后根据先进先出的思想,用广度优先遍历(BFS)的方式,一次从queue中弹出一个节点,判断该节点和B的头结点是否val相同,如果相同,那么以此两个节点作为一个递归函数的参数,判断其各自代表的子树是否相同。

构想此思路之前,就误解了题意,还是“子结构”和子树的问题,其实两者的解决思路相同,只不过递归终止的条件略有区别罢了。

代码的注释中,有对递归的详细解释。

上代码:

	package niuke.sward2offer.substructureOfTree;

	import java.util.LinkedList;
	import java.util.List;
	import java.util.Queue;
	
	/**
	 * T:树的子结构
	 * 
	 * 题目描述
	 * 输入两颗二叉树A,B,判断B是不是A的子结构。
	 * 
	 * date: 2015.11.1
	 * 
	 * @author SSS
	 *
	 */
	class TreeNode {
	    int val = 0;
	    TreeNode left = null;
	    TreeNode right = null;
	
	    public TreeNode(int val) {
	        this.val = val;
	
	    }
	
	}
	
	public class Solution {

	public boolean HasSubtree(TreeNode root1, TreeNode root2) {
		boolean flag = false;
		Queue<TreeNode> queue = new LinkedList<TreeNode>();
		if (root1 == null || root2 == null) {
			return false;
		}
		queue.offer(root1);
		while (queue.size() != 0) {
			TreeNode tempNode = queue.poll();
			if (tempNode.val == root2.val) {
				flag = this.isEqual(tempNode, root2);
			}
			
			if (flag) {
				break;
			}
			
			// 广度遍历的方式,遍历第一个树A的所有节点
			if (tempNode.left != null) {
				queue.offer(tempNode.left);
			}
			if (tempNode.right != null) {
				queue.offer(tempNode.right);
			}
		}
		
		return flag;
	}
	
	/**
	 * 判断两个子树是否相同
	 * 
	 * 思想:判断其两个子节点的值是否相同,如果相同,就返回true
	 * 
	 * isEqual(param1, param2):两个参数,其值是否相同,相同就看其各自的两个孩子节点是否相同,不相同就直接返回false
	 * 终止条件:如果都为null,说明都遍历完毕,返回true
	 * 
	 * @param firstNode
	 * @param secondNode
	 * @return
	 */
	public boolean isEqual(TreeNode firstNode, TreeNode secondNode) {
		
		// 判断的是“子结构”
		if (secondNode == null) {
			return true;
		}
		
		/*
		// 判断的是“子树”
		if (firstNode == null && secondNode == null) {
			return true;
		}
		*/
		
		boolean flag = false;
		
		// 只有当前两个参数都不为null,且其值相同时,才能进一步的作比较,否则直接返回false
		if (firstNode != null && secondNode != null && firstNode.val == secondNode.val) {
			flag = isEqual(firstNode.left, secondNode.left) && isEqual(firstNode.right, secondNode.right);
		}
		
		return flag;
	}
	
	 public static void main(String[] args) {  
	        
	       TreeNode root1 = new TreeNode(2);
	       TreeNode left1 = new TreeNode(1);
	       TreeNode right2 = new TreeNode(3);
	       root1.left = left1;
	       root1.right = right2;
	       
	       TreeNode left11 = new TreeNode(4);
	       TreeNode right12 = new TreeNode(5);
	       left1.left = left11;
	       left1.right = right12;
	       
	       TreeNode right22 = new TreeNode(6);
	       right2.right = right22;
	       
	       TreeNode root2 = new TreeNode(2);
	       TreeNode lefta = new TreeNode(4);
	       TreeNode righta = new TreeNode(3);
	   //    root2.left = lefta;
	       root2.right = righta;
	       
	       Solution solution = new Solution();
	       System.out.println(solution.HasSubtree(root1, root2));
	    }  
	}

更多2019年的技术文章,欢迎关注我的微信公众号:码不停蹄的小鼠松(微信号:busy_squirrel),也可扫下方二维码关注获取最新文章哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值