剑指offer——树的子结构 (JAVA代码)

版权声明:本文为博主原创文章,未经博主允许不得转载。

题目描述

  输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)。

解题思路:

  首先看牛客网给出的测试用例:

  

  一般对于树的操作不像链表一样,操作更复杂,如果使用循环遍历的话,对于非完全二叉树规律难寻,一般通用的方法就是使用递归求解,本题也不例外,同样使用递归求解,求解的大体思路是首先判断B的根节点和A的根节点是否相同(这里的相同是指节点的值相同并且左右子节点相同),如果相同比较他们的左右子节点,这一步骤是相同的,可以用递归完成,直到B遍历到每个尾节点,如果这一过程比较的所有节点是相同的,则证明B是A的子结构。如果B的根节点和A的根节点不同,则A向他的左右子节点滑动,然后继续跟B的子节点比较,步骤同上。

  递归的使用可以用我总结的三步来完成。求解过程如下:

  1. 递归截止条件。

  递归的截止条件是为了递归能够避免无限循环下去,首先来分析什么情况下递归截止返回遍历结果,(1)根据题目要求,如果B数是个空树,递归截止。(2)如果被遍历的树A是空树,自然而然递归截止。(3)如果比较的是B的尾节点,无法进行下去,递归也会截止。(4)如果A树从头遍历到尾始终没有和B的节点相同的节点,递归截止。

  2. 递归的前后衔接。

  如果A的根节点值以及左右子节点情况和B的根节点完全相同,那么A和B都继续滑动到他们的左右子节点进行比较;如果A的根节点值和B的根节点值是相同的,但是左右子节点的情况是不相同的,那么只滑动A到他的左右子节点再与B比较。如果A的根节点的值和B的根节点的值不相同,那么A直接滑动到他的左右自己点再和B的根节点比较,直到遍历完成。

  3. 递归节点数据的处理。

  根据题目,本题目中用到的递归并没有数据处理,只是比较判断两个树节点是否相同。对于其他递归,可以具体情况具体对待。

源码:

 1     /**
 2      * 输入两棵二叉树A,B,判断B是不是A的子结构。
 3      * @param root1 A树
 4      * @param root2 B数
 5      * @return
 6      */
 7     public static boolean HasSubtree(TreeNode root1,TreeNode root2) {
 8
 9         if (root2==null) {        //空树不是任意一个树的子结构
10             return false;
11         }
12         if (root1==null) {        //如果A为空,那肯定返回false
13             return false;
14         }
15         if(root2.val==root1.val){        //A和B比较的根节点的值相同
16
17             if (root2.left==null&&root2.right==null) {        //比较的节点是B的尾节点,递归截止
18                 return true;
19             }
20             //下面三种比较的是比较的节点完全相同的情况
21             if ((root2.left!=null&&root2.right!=null)&&(root1.left!=null&&root1.right!=null)&&root2.left.val==root1.left.val&&root2.right.val==root1.right.val) {
22                 return HasSubtree(root1.left,root2.left)&& HasSubtree(root1.right,root2.right);
23             }else if ((root2.left!=null&&root2.right==null)&&(root1.left!=null&&root1.right==null)&&root2.left.val==root1.left.val) {
24                 return HasSubtree(root1.left,root2.left);
25             }else if ((root2.left==null&&root2.right!=null)&&(root1.left==null&&root1.right!=null)&&root2.right.val==root1.right.val) {
26                 return HasSubtree(root1.right,root2.right);
27             }else{        //比较的节点不同,A向左右子节点移动一个再比较
28                 if (root1.left!=null&&root1.right!=null) {
29                     return  HasSubtree(root1.left,root2)|| HasSubtree(root1.right,root2);
30                 }else if(root1.left==null&&root1.right!=null){
31                     return  HasSubtree(root1.right,root2);
32                 }else if(root1.left!=null&&root1.right==null){
33                     return  HasSubtree(root1.left,root2);
34                 }else {
35                     return false;
36                 }
37             }
38         //比较的根节点的值不相同,直接向左右子节点滑动
39         }else if(root1.left!=null&&root1.right==null){
40             return HasSubtree(root1.left,root2);
41         }else if(root1.left==null&&root1.right!=null){
42             return HasSubtree(root1.right,root2);
43         }else{
44             return false;
45         }
46     }
时间: 2024-10-12 04:48:07

剑指offer——树的子结构 (JAVA代码)的相关文章

剑指offer树的子结构python

题目描述 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 思路 首先遍历a树,找和b树根结点值相等的结点,找到后判断是不是子树. 判断是不是子树的时候,用递归的方法,判断根节点,再判断左子右子. 代码 # -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class S

剑指 offer 树的子结构

题目描述: 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构). 第一遍没写出来错误点:认为首先应该找到pRoot1等于pRoot2的节点,但是递归就是自己在不断递归中寻找相等的节点的.判断是否相等可以完全放到另外一个函数中进行判断.主函数主要就是看结果,比较相等可以完全放到另外一个函数中去. /* struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; TreeN

剑指offer——树的子结构

题目链接:输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 解题思路: 递归的方法,先判断根节点,如果相等,判断左子树以及右子树. 1 /** 2 public class TreeNode { 3 int val = 0; 4 TreeNode left = null; 5 TreeNode right = null; 6 7 public TreeNode(int val) { 8 this.val = val; 9 10 } 11 12 } 13

《剑指Offer》——Singleton(Java版)

1.单例模式的定义 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 2.单例模式的特点 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类必须给所有其他对象提供这一实例. 3.单例模式的Java代码 单例模式分为懒汉式(需要才去创建对象)和饿汉式(创建类的实例时就去创建对象). 4.饿汉式 在静态代码块实例对象 //在静态代码块实例对象 public class Singleton { private static Singleton singleton

剑指offer面试题14(Java版):调整数组顺序使奇数位于偶数的前面

题目:输入一个整数数组.实现一个函数来调整该数组中数字的顺序.使得全部奇数位于数组的前半部分.全部偶数位于数组的后半部分. 1.基本实现: 假设不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的全部的数字往前面挪动一位. 挪完之后在数组的末尾有一个空位.这时把该偶数放入这个空位. 因为没碰到一个偶数就须要移动O(n)个数字.因此总的时间复杂度是O(n2).可是,这样的方法不能让面试官惬意.只是假设我们在听到题目之后立就可以以说出这个解法,

剑指Offer编程题(Java实现)——二维数组中的查找

题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 解题思路 根据排序特点,该二维数组中的一个数,小于它的数一定在其左边,大于它的数一定在其下边. 因此,从右上角开始查找,就可以根据 target 和当前元素的大小关系来缩小查找区间,当前元素的查找区间为左下角的所有元素. 时间复杂度 O(M + N),空间复杂度 O(1).其中 M 为行数,N

剑指Offer编程题(Java实现)——反转链表

题目描述 输入一个链表,反转链表后,输出新链表的表头. 思路一 使用头插法迭代进行反转 实现 /* public class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } }*/ public class Solution { public ListNode ReverseList(ListNode head) { ListNode newHead = new ListNode(-1

【Java】 剑指offer(7) 二叉树的下一个结点

本文参考自<剑指offer>一书,代码采用Java语言. 题目 给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点? 树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指针. 思路 首先自己在草稿纸上画图,进行分析(不再展开).可以发现下一个结点的规律为: 1.若当前结点有右子树时,其下一个结点为右子树中最左子结点: 2.若当前结点无右子树时, (1)若当前结点为其父结点的左子结点时,其下一个结点为其父结点: (2)若当前结点为其父结点的右子结点时,继续向上遍

【Java】 剑指offer(31)从上往下打印二叉树

本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 (一)从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印. (二)从上到下按层打印二叉树,同一层的结点按从左到右的顺序打印,每一层打印到一行. (三)请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 思路 (一)不分行从上往下打印二叉树:该题即为对二叉树的层