面试大总结之二:Java搞定面试中的二叉树题目

这是本系列的第二篇,与前一篇 面试大总结之一:Java搞定面试中的链表题目 相比,二叉树的题目可以变化的就更多了。本文还是参考整合重写了《轻松搞定面试中的二叉树题目》和《算法大全(3) 二叉树》两篇大作。本文一个小亮点就是几乎每一道题都用了递归和迭代两种方法写过一遍,因为面试时往往可能会被要求写不擅长的那一种。这一千多行的记录也是我在面试摸索过程中的一个小笔记,备份与此。请大神们轻拍指正。今后我也会不断更新加入新题新方法。


package BinaryTreeSummary;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;

/**
 * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888  轻松搞定面试中的二叉树题目
 * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html  算法大全(3) 二叉树
 * 
 * TODO: 一定要能熟练地写出所有问题的递归和非递归做法!
 *
 * 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代)
 * 2. 求二叉树的深度: getDepthRec(递归),getDepth 
 * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec
 * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2)
 * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法!)
 * 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL
 * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel
 * 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf
 * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame
 * 9. 判断二叉树是不是平衡二叉树:isAVLRec
 * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):mirrorRec, mirrorCopyRec
 * 10.1 判断两个树是否互相镜像:isMirrorRec
 * 11. 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec, getLastCommonParentRec2
 * 12. 求二叉树中节点的最大距离:getMaxDistanceRec
 * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec
 * 14.判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec
 * 
 */
public class Demo {

	/*
	 			 1 
		        / \ 
		       2   3 
		      / \   \ 
		     4  5   6 
	 */
	public static void main(String[] args) {
		TreeNode r1 = new TreeNode(1);
		TreeNode r2 = new TreeNode(2);
		TreeNode r3 = new TreeNode(3);
		TreeNode r4 = new TreeNode(4);
		TreeNode r5 = new TreeNode(5);
		TreeNode r6 = new TreeNode(6);
		
		r1.left = r2;
		r1.right = r3;
		r2.left = r4;
		r2.right = r5;
		r3.right = r6;
		
//		System.out.println(getNodeNumRec(r1));
//		System.out.println(getNodeNum(r1));
//		System.out.println(getDepthRec(r1));
//		System.out.println(getDepth(r1));
		
//		preorderTraversalRec(r1);
//		System.out.println();
//		preorderTraversal(r1);
//		System.out.println();
//		inorderTraversalRec(r1);
//		System.out.println();
//		inorderTraversal(r1);
//		System.out.println();
//		postorderTraversalRec(r1);
//		System.out.println();
//		postorderTraversal(r1);
//		System.out.println();
//		levelTraversal(r1);
//		System.out.println();
//		levelTraversalRec(r1);
//		System.out.println();
		
//		TreeNode tmp = convertBSTRec(r1);
//		while(true){
//			if(tmp == null){
//				break;
//			}
//			System.out.print(tmp.val + " ");
//			if(tmp.right == null){
//				break;
//			}
//			tmp = tmp.right;
//		}
//		System.out.println();
//		while(true){
//			if(tmp == null){
//				break;
//			}
//			System.out.print(tmp.val + " ");
//			if(tmp.left == null){
//				break;
//			}
//			tmp = tmp.left;
//		}
		
		
//		TreeNode tmp = convertBST2DLL(r1);
//		while(true){
//			if(tmp == null){
//				break;
//			}
//			System.out.print(tmp.val + " ");
//			if(tmp.right == null){
//				break;
//			}
//			tmp = tmp.right;
//		}
		
//		System.out.println(getNodeNumKthLevelRec(r1, 2));
//		System.out.println(getNodeNumKthLevel(r1, 2));
		
//		System.out.println(getNodeNumLeafRec(r1));
//		System.out.println(getNodeNumLeaf(r1));
		
//		System.out.println(isSame(r1, r1));
//		inorderTraversal(r1);
//		System.out.println();
//		mirror(r1);
//		TreeNode mirrorRoot = mirrorCopy(r1);
//		inorderTraversal(mirrorRoot);
		
		System.out.println(isCompleteBinaryTree(r1));
		System.out.println(isCompleteBinaryTreeRec(r1));
		
	}

	private static class TreeNode {
		int val;
		TreeNode left;
		TreeNode right;

		public TreeNode(int val) {
			this.val = val;
		}
	}

	/**
	 * 求二叉树中的节点个数递归解法: O(n)
	 * (1)如果二叉树为空,节点个数为0 
	 * (2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 +
	 *    	      右子树节点个数 + 1
	 */
	public static int getNodeNumRec(TreeNode root) {
		if (root == null) {
			return 0;
		} else {
			return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;
		}
	}
	
	/**
	 *  求二叉树中的节点个数迭代解法O(n):基本思想同LevelOrderTraversal,
	 *  即用一个Queue,在Java里面可以用LinkedList来模拟 
	 */
	public static int getNodeNum(TreeNode root) {
		if(root == null){
			return 0;
		}
		int count = 1;
		Queue<TreeNode> queue = new LinkedList<TreeNode>();
		queue.add(root);
		
		while(!queue.isEmpty()){
			TreeNode cur = queue.remove();		// 从队头位置移除
			if(cur.left != null){			// 如果有左孩子,加到队尾
				queue.add(cur.left);
				count++;
			}
			if(cur.right != null){		// 如果有右孩子,加到队尾
				queue.add(cur.right);
				count++;
			}
		}
		
		return count;
	}

	/**
	 * 求二叉树的深度(高度) 递归解法: O(n)
	 * (1)如果二叉树为空,二叉树的深度为0 
	 * (2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
	 */
	public static int getDepthRec(TreeNode root) {
		if (root == null) {
			return 0;
		}

		int leftDepth = getDepthRec(root.left);
		int rightDepth = getDepthRec(root.right);
		return Math.max(leftDepth, rightDepth) + 1;
	}
	
	/**
	 * 求二叉树的深度(高度) 迭代解法: O(n)
	 * 基本思想同LevelOrderTraversal,还是用一个Queue
	 */
	public static int getDepth(TreeNode root) {
		if(root == null){
			return 0;
		}
		
		int depth = 0;						
  • 12
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 24
    评论
(1)非递归定义 (tree)是由n(n≥0)个结点组成的有限集合。n=0的称为空;n>0的T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗,由此我们可以给出的递归定义。 (tree)是由n(n≥0)个结点组成的有限集合。n=0的称为空;n>0的T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其每个集合Ti(0≤i<m)本身又是一棵,称为根的子(subtree)。 2、掌握的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、的高度 (4) 边、路径 (5) 无序、有序 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子或者右子,亦或者左、右子皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值