LeetCode——二叉树篇(四)

 刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com 

 二叉树的定义及创建见:

LeetCode ACM模式——二叉树篇(一)_要向着光的博客-CSDN博客

目录

101. 对称二叉树

递归

 使用队列

100. 相同的树

572. 另一棵树的子树

222. 完全二叉树的节点个数

110. 平衡二叉树

257. 二叉树的所有路径


101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

递归

/**
 * @author light
 * @Description 对称二叉树
 * 给你一个二叉树的根节点 root , 检查它是否轴对称。
 * @create 2023-08-18 10:28
 */
public class IsSymmetricTest {
	public static void main(String[] args) {
		Integer[] arr={2,3,3,4,5,5};
		BinaryTree2 tree2=new BinaryTree2(arr); //按数组方式创建二叉树
		//递归
		boolean symmetric = isSymmetric(tree2.root);
		System.out.println(symmetric);
		
		
	}
	public static boolean isSymmetric(TreeNode root) {
		if(root==null){
			return true;
		}
		//递归
		return compare_Recursion(root.left,root.right);
	}

	//递归
	private static boolean compare_Recursion(TreeNode left, TreeNode right) {
		if(left!=null&&right==null){
			return false;
		} else if (left==null&&right!=null) {
			return false;
		} else if (left == null && right == null) {
			return true;
		} else if (left.val!=right.val) {
			return false;
		}

		boolean outSide=compare_Recursion(left.left,right.right); //左子树:左;右子树:右
		boolean inSide=compare_Recursion(left.right,right.left); //左子树:右; 右子树:左
		boolean isSame=outSide&&inSide;

		return isSame;
	}
}

 使用队列

import java.util.Deque;
import java.util.LinkedList;

/**
 * @author light
 * @Description 对称二叉树
 * 给你一个二叉树的根节点 root , 检查它是否轴对称。
 * @create 2023-08-18 10:28
 */
public class IsSymmetricTest {
	public static void main(String[] args) {
		Integer[] arr={2,3,3,4,5,5};
		BinaryTree2 tree2=new BinaryTree2(arr); //按数组方式创建二叉树
		//使用队列
		System.out.println(isSymmetric_Queue(tree2.root));
		
	}

	//使用队列
	public static boolean isSymmetric_Queue(TreeNode root) {
		if(root==null){
			return true;
		}
		Deque<TreeNode> que=new LinkedList<>();
		que.offer(root.left);
		que.offer(root.right);
		while(!que.isEmpty()){
			TreeNode leftNode=que.pollFirst();
			TreeNode rightNode=que.pollFirst();
			if(leftNode==null&&rightNode==null){
				continue;
			}
			if(leftNode!=null&&rightNode==null){
				return false;
			} else if (leftNode==null&&rightNode!=null) {
				return false;
			} else if (leftNode.val!=rightNode.val) {
				return false;
			}
			que.offer(leftNode.left);
			que.offer(rightNode.right);
			que.offer(leftNode.right);
			que.offer(rightNode.left);
		}
		return true;
	}
}

100. 相同的树

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

/**
 * @author light
 * @Description 相同的数
 * @create 2023-08-18 11:32
 */
public class IsSameTreeTest {
	public static void main(String[] args) {
		Integer[] p={1,2,3};
		BinaryTree2 tree1=new BinaryTree2(p); //按数组方式创建二叉树
		Integer[] q={1,2,3};
		BinaryTree2 tree2=new BinaryTree2(q); //按数组方式创建二叉树
		System.out.println(isSameTree(tree1.root, tree2.root));

	}
	public static boolean isSameTree(TreeNode p, TreeNode q) {
		if(p==null&&q==null){
			return true;
		}
		//if(p==null&&q!=null){
		//	return false;
		//} else if (p!= null && p== null) {
		//	return false;
		//} else if (p.val!= q.val ) {
		//	return false;
		//}
		if(p==null||q==null){
			return false;
		}else if(p.val!=q.val){
			return false;
		}
		boolean left=isSameTree(p.left,q.left); //左
		boolean right=isSameTree(p.right,q.right); //右
		boolean isSame=left&&right; //中
		return isSame;
	}
}

572. 另一棵树的子树

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。


/**
 * @author light
 * @Description 另一棵树的子树
 *
 * 给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。
 * 如果存在,返回 true ;否则,返回 false 。
 * 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。
 * tree 也可以看做它自身的一棵子树。
 *
 * (思路:要判断一个树 t 是不是树 s 的子树,那么可以判断 t 是否和树 s 的任意子树相等。那么就转化成 100. Same Tree。
 * 即,这个题的做法就是在 s 的每个子节点上,判断该子节点是否和 t 相等。
 *
 * 判断两个树是否相等的三个条件是与的关系,即:
 * 当前两个树的根节点值相等;
 * 并且,s 的左子树和 t 的左子树相等;
 * 并且,s 的右子树和 t 的右子树相等。
 * 而判断 t 是否为 s 的子树的三个条件是或的关系,即:
 *
 * 当前两棵树相等;
 * 或者,t 是 s 的左子树;
 * 或者,t 是 s 的右子树。
 *
 * 作者:负雪明烛
 * 链接:https://leetcode.cn/problems/subtree-of-another-tree/solutions/235634/dui-cheng-mei-pan-duan-zi-shu-vs-pan-duan-xiang-de/
 * 来源:力扣(LeetCode)
 * 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 * @create 2023-08-18 11:46
 */
public class IsSubtreeTest {
	public static void main(String[] args) {
		Integer[] root = {1,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1,2};
		Integer[] subRoot = {1,null,1,null,1,null,1,null,1,null,1,2};
		BinaryTree2 tree1=new BinaryTree2(root); //按数组方式创建二叉树
		BinaryTree2 tree2=new BinaryTree2(subRoot); //按数组方式创建二叉树
		System.out.println(isSubtree(tree1.root, tree2.root));
	}

	public static boolean isSubtree(TreeNode root, TreeNode subRoot) {
		//判断是否是子树
		if(root==null&&subRoot==null){
			return true;
		}
		if(root==null||subRoot==null){
			return false;
		}
		return isSameTree(root,subRoot)||isSubtree(root.left,subRoot)||isSubtree(root.right,subRoot);
	}

	private static boolean isSameTree(TreeNode s, TreeNode t) {
		//这里转化为两棵树是否相等
		if(s==null&&t==null){
			return true;
		}
		if(s==null||t==null){
			return false;
		} else if (s.val!= t.val) {
			return false;
		}

		return isSameTree(s.left,t.left)&&isSameTree(s.right,t.right);
	}
}

222. 完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

/**
 * @author light
 * @Description 完全二叉树的节点个数
 *
 * (思路:当完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
 *
 * 对于情况一,可以直接用 2^树深度 - 1 来计算,注意这里根节点深度为1。
 * 对于情况二,分别递归左孩子和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,
 *		然后依然可以按照情况1来计算。
 * @create 2023-08-18 14:52
 */
public class CountNodesTest {
	public static void main(String[] args) {
		Integer[] arr = {1,2,3,4,5,6};
		BinaryTree2 tree=new BinaryTree2(arr); //按数组方式创建二叉树
		System.out.println(countNodes(tree.root));
	}
	public static int countNodes(TreeNode root) {
		/*   递归:普通二叉树
		//if(root==null){
		//	return 0;
		//}
		左
		//int leftNum=countNodes(root.left);
		//int rightNum=countNodes(root.right);
		//int res=leftNum+rightNum+1;
		//return res;

		 */

		//完全二叉树
		if(root==null){
			return 0;
		}
		TreeNode leftNode=root.left;
		TreeNode rightNode=root.right;
		int leftDepth=0; //为了便于计算
		int rightDepth=0;
		while(leftNode!=null){
			leftNode=leftNode.left;
			leftDepth++;
		}
		while(rightNode!=null){
			rightNode=rightNode.right;
			rightDepth++;
		}
		if(leftDepth==rightDepth){
			return (2<<leftDepth)-1;  //满二叉树结点数计算 ;注意(2<<1) 相当于2^2,
		}

		int leftNum=countNodes(root.left);  //左
		int rightNum=countNodes(root.right); //右
		int res=leftNum+rightNum+1; //中
		return res;



	}
}

110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

 

/**
 * @author light
 * @Description 平衡二叉树
 * @create 2023-08-18 16:02
 */
public class IsBalancedTest {

	public static boolean isBalanced(TreeNode root) {
		if(root==null){
			return true;
		}
		return getHeight(root)!=-1?true:false;
	}

	private static int getHeight(TreeNode root) {
		if(root==null){
			return 0;
		}
		int left=getHeight(root.left);
		if(left==-1){
			return -1;
		}
		int right=getHeight(root.right);
		if(right==-1){
			return  -1;
		}
		if(Math.abs(left-right)<=1){
			//平衡二叉树
			return 1+Math.max(left,right);
		}else {
			return -1;
		}
	}
}

257. 二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

import java.util.ArrayList;
import java.util.List;

/**
 * @author light
 * @Description 二叉树的所有路径
 * @create 2023-08-18 16:25
 */
public class BinaryTreePathsTest {
	public static List<String> binaryTreePaths(TreeNode root) {
		List<String> res=new ArrayList<>(); //存放结果
		if(root==null){
			return res;
		}
		List<Integer> path=new ArrayList<>(); //存放路径变量
		traversal(root,path,res);
		return res;
	}

	private static void traversal(TreeNode root, List<Integer> path, List<String> res) {

		path.add(root.val); //前序遍历:中

		if(root.left==null&&root.right==null){ //遇到叶子结点,及收获结果的时候
			StringBuilder sb=new StringBuilder();
			for (int i = 0; i < path.size()-1; i++) {
				sb.append(path.get(i)).append("->");
			}
			sb.append(path.get(path.size()-1));
			res.add(sb.toString());
			return;
		}
		if(root.left!=null){
			traversal(root.left,path,res); //前序遍历 左
			path.remove(path.size()-1);
		}
		if(root.right!=null){
			traversal(root.right,path,res); //前序遍历  右
			path.remove(path.size()-1);
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值