剑指Offer面试题(第五天)面试题7、8

* 面试题7:重建二叉树


     *    题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。
     *        假设输入的前序遍历和中序遍历的结果中都不包含重复的数字。
     *        例如:输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
     *            则重建二叉树并输出它的头节点
     *        二叉树节点的定义:
     *        struct BinaryTreeNode{
     *            int m_nValue;            //value
     *        BinaryTreeNode* m_pLeft;   //左子树
     *        BinaryTreeNode* m_pRight;  //右子树
     *        }
     *        
     *   思路:先找出根节点,然后利用递归方法构造二叉树

 

 

package Test;

import java.awt.print.Printable;
import java.util.Arrays;

public class No7construct {

	/*
	 * 面试题7:重建二叉树
	 *    题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。
	 *        假设输入的前序遍历和中序遍历的结果中都不包含重复的数字。
	 *        例如:输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
	 *            则重建二叉树并输出它的头节点
	 *        二叉树节点的定义:
	 *        struct BinaryTreeNode{
	 *        	int m_nValue;            //value
	 *        BinaryTreeNode* m_pLeft;   //左子树
	 *        BinaryTreeNode* m_pRight;  //右子树
	 *        }
	 *        
	 *   思路:先找出根节点,然后利用递归方法构造二叉树
	 * */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		No7construct c = new No7construct();
		
		int[] pre = {1,2,4,7,3,5,6,8};//前序遍历序列
		int[] in = {4,7,2,1,5,3,8,6};//中序遍历序列
		
		//返回后序遍历结果
		TreeNode t = c.Construct(pre,in);
		System.out.println("后序遍历结果为:");
		c.lastOrder(t);
	}

	

	//通过前序和中序遍历序列重建二叉树
	public TreeNode Construct(int[] pre, int[] in) {
		// TODO Auto-generated method stub
		if(pre == null||in == null) {
			return null;			
		}
		if(pre.length == 0||in.length == 0) {
			return null;
		}
		if(pre.length != in.length) {
			return null;
		}
		
		TreeNode root = new TreeNode(pre[0]);  //根节点为前序遍历的第一个
		for(int i = 0;i<pre.length;i++) {
			if(pre[0] == in[i]) {    //遍历中序序列 in[i]
				/*在中序遍历序列中查找根节点,找到根节点,
				 *然后可得到左子树root.left和右子树root.left
				 *    然后再将左子树(前序+中序)作为一个二叉树,进行中序遍历找到其中的根节点,
				 *    然后根据根节点得到左子树root.left和右子树root.right
				 * */
				
				root.left = Construct(Arrays.copyOfRange(pre, 1,i+1),Arrays.copyOfRange(in, 0, i));
	            //构建子树时可以直接使用Arrays.copyOfRange(int []original,int from,int to),original为原始的int型数组,from为开始角标值,to为终止角标值。(其中包括from角标,不包括to角标。即处于[from,to)左闭右开状态

				root.right = Construct(Arrays.copyOfRange(pre, i+1, pre.length),Arrays.copyOfRange(in, i+1, in.length));
			
			}
			
		}
		return root;
	}
	
	
	
	//后序遍历结果    重建后的二叉树后序遍历方式输出二叉树
		public void lastOrder(TreeNode t) {
			// TODO Auto-generated method stub
			if(t != null) {
				lastOrder(t.left);
				lastOrder(t.right);
				System.out.print(t.val+" ");
			}
			
		}

}


class TreeNode{
	int val;
	TreeNode left;
	TreeNode right;
	
	TreeNode(int val){
		this.val = val;
	}
	
}

*面试题8:二叉树的下一个节点

     *题目:给定一棵二叉树和其中的一个节点,如何找到中序遍历序列的下一个节点?
     *    树中的节点除了有两个分别指向左、右子节点的指针 ,还有一个指向父节点的指针。
     *    
     *    总结一下,下一个节点可能出现的位置:
     *    1.若这一节点有右子树,则它下一个节点就是它右子树的最左子节点
     *    2.若这一节点没有右子树,但是它是父节点的左子节点,则它下一个节点就是它的父节点
     *    3.若这一节点(节点A)没有右子树,且是父节点的右子节点,
     *         那就沿着它(节点A)的父节点(节点B)一直往上找,。。。
     *         直到找到一个节点(节点C)是其(节点C)父节点的左子节点(若有这样的节点),
     *         则它下一个节点就是  找到的这个节点(节点C)的父节点
     *         若无这样的节点,则它下一个节点为null
     *   (2情况其实是3的特殊情况  刚好其父节点就是左子节点)

 

 

package Test;

public class No8getNext {

	/*
	 *面试题8:二叉树的下一个节点
	 *题目:给定一棵二叉树和其中的一个节点,如何找到中序遍历序列的下一个节点?
	 *    树中的节点除了有两个分别指向左、右子节点的指针 ,还有一个指向父节点的指针。
	 *    
	 *    总结一下,下一个节点可能出现的位置:
	 *    1.若这一节点有右子树,则它下一个节点就是它右子树的最左子节点
	 *    2.若这一节点没有右子树,但是它是父节点的左子节点,则它下一个节点就是它的父节点
	 *    3.若这一节点(节点A)没有右子树,且是父节点的右子节点,
	 *         那就沿着它(节点A)的父节点(节点B)一直往上找,。。。
	 *         直到找到一个节点(节点C)是其(节点C)父节点的左子节点(若有这样的节点),
	 *         则它下一个节点就是  找到的这个节点(节点C)的父节点
	 *         若无这样的节点,则它下一个节点为null
	 *   (2情况其实是3的特殊情况  刚好其父节点就是左子节点)
	 * */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		No8getNext n = new No8getNext();
		//调用No8getNext的方法    也可以使用TreeNode类创建对象
		
		TreeNode_p a = new TreeNode_p(1);
		TreeNode_p b = new TreeNode_p(2);
		TreeNode_p c = new TreeNode_p(3);
		TreeNode_p d = new TreeNode_p(4);
		TreeNode_p e = new TreeNode_p(5);
		TreeNode_p f = new TreeNode_p(6);
		TreeNode_p g = new TreeNode_p(7);
		TreeNode_p h = new TreeNode_p(8);
		TreeNode_p i = new TreeNode_p(9);
		
		a.left = b;
		a.right = c;
		
		
		b.left = d;
		b.right = e;

	    c.left = f;
	    c.right = g;

	    e.left = h;
	    e.right = i;

	    h.parent = e;
	    i.parent = e;

	    e.parent = b;
	    d.parent = b;

	    f.parent = c;
	    g.parent = c;

	    b.parent = a;
	    c.parent = a;
	
	    TreeNode_p next = n.getNext(g);
	    if(next != null) {
	    	System.out.println(g.val+"节点的下一个节点为"+next.val);
	    }
	    else
	    	System.out.println(g.val+"节点无下一个节点");
	}

	public TreeNode_p getNext(TreeNode_p t) {
		// TODO Auto-generated method stub
		if(t == null) {
			return null;
		}
		
		if(t.right != null) {
			//若有右子树,则它下一个节点为它右子树的最左子节点
			t = t.right; 
			while(t.left != null){		 
				t = t.left;
			}
			return t;
		}
		
		if(t.right == null) {
			//若无右子树,看是否是其父节点们的左子节点,
			//若是则下一节点为它父节点
			while(t.parent != null) {
				if(t.parent.left == t) {
					return t.parent;
					
				}
				t = t.parent;  
				
			}
			
		}
		return null;
	}
	

	

}

class TreeNode_p{
	int val;
	TreeNode_p left;
	TreeNode_p right;
	TreeNode_p parent;
	TreeNode_p(int val){
		this.val = val;
	}
	
}

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值