剑指Offer笔记—— 从尾到头打印链表 重建二叉树

来源:互联网 发布:数据挖掘 答案 韩家炜 编辑:程序博客网 时间:2024/05/29 10:18

3、面试题5:从尾到头打印链表

题目大致为:

    输入一个链表的头结点,从未到头反过来打印每个结点的值。

思路:

    题目的要求是进行从尾到头输出,而链表的查找只能是顺序查找,栈的结构满足这样的条件:先进后出。同样,也可以使用递归的方式求解。

Java代码:

链表类:

[java] view plain copy
  1. package org.algorithm.pointtooffer;  
  2.   
  3. /** 
  4.  * 链表的节点 
  5.  *  
  6.  * @author dell 
  7.  *  
  8.  */  
  9. public class ListNode {  
  10.     private int value;  
  11.     private ListNode next;  
  12.   
  13.     public ListNode(int value) {  
  14.         this.value = value;  
  15.     }  
  16.   
  17.     public ListNode(int value, ListNode next) {  
  18.         this.value = value;  
  19.         this.next = next;  
  20.     }  
  21.   
  22.     public void setValue(int value) {  
  23.         this.value = value;  
  24.     }  
  25.   
  26.     public void setNext(ListNode next) {  
  27.         this.next = next;  
  28.     }  
  29.   
  30.     public int getValue() {  
  31.         return this.value;  
  32.     }  
  33.   
  34.     public ListNode getNext() {  
  35.         return this.next;  
  36.     }  
  37.   
  38. }  


Java实现:

[java] view plain copy
  1. package org.algorithm.pointtooffer;  
  2.   
  3. import java.util.Stack;  
  4.   
  5. /** 
  6.  * 面试题5:从尾到头打印链表 
  7.  *  
  8.  * @author dell 
  9.  *  
  10.  */  
  11. public class Item05 {  
  12.     /** 
  13.      * 测试 
  14.      *  
  15.      * @param args 
  16.      */  
  17.     public static void main(String args[]) {  
  18.         // 构建链表  
  19.         ListNode head = new ListNode(0);  
  20.         ListNode node_one = new ListNode(1);  
  21.         ListNode node_two = new ListNode(2);  
  22.         ListNode node_three = new ListNode(3);  
  23.         ListNode node_four = new ListNode(4);  
  24.         head.setNext(node_one);  
  25.         node_one.setNext(node_two);  
  26.         node_two.setNext(node_three);  
  27.         node_three.setNext(node_four);  
  28.         node_four.setNext(null);  
  29.         System.out.println("第一种方式,递归实现:");  
  30.         printListReverse_1(head);  
  31.         //换行  
  32.         System.out.println();  
  33.         System.out.println("第二种方式,非递归实现:");  
  34.         printListReverse_2(head);  
  35.     }  
  36.   
  37.     /** 
  38.      * 用递归实现 
  39.      *  
  40.      * @param head 
  41.      */  
  42.     public static void printListReverse_1(ListNode head) {  
  43.         if (head != null) {  
  44.             if (head.getNext() != null) {  
  45.                 printListReverse_1(head.getNext());  
  46.             }  
  47.             System.out.print(head.getValue() + "、");  
  48.         }  
  49.     }  
  50.   
  51.     /** 
  52.      * 用栈实现 
  53.      *  
  54.      * @param head 
  55.      */  
  56.     public static void printListReverse_2(ListNode head) {  
  57.         Stack<Integer> s = new Stack<Integer>();  
  58.         ListNode p = head;  
  59.         // 进栈  
  60.         while (p != null) {  
  61.             s.push(p.getValue());  
  62.             p = p.getNext();  
  63.         }  
  64.   
  65.         // 出栈  
  66.         while (!s.isEmpty()) {  
  67.             System.out.print(s.pop() + "、");  
  68.         }  
  69.         System.out.println();  
  70.     }  
  71. }  


4、面试题6:重建二叉树

题目大致为:

    已知前序遍历序列和中序遍历序列,要求重建二叉树

二叉树的结点定义:

 

[java] view plain copy
  1. package org.algorithm.pointtooffer;  
  2.   
  3. public class BinaryTreeNode {  
  4.     private int value;  
  5.     private BinaryTreeNode left;  
  6.     private BinaryTreeNode right;  
  7.   
  8.     public BinaryTreeNode(int value) {  
  9.         this.value = value;  
  10.     }  
  11.   
  12.     public BinaryTreeNode(int value, BinaryTreeNode left, BinaryTreeNode right) {  
  13.         this.value = value;  
  14.         this.left = left;  
  15.         this.right = right;  
  16.     }  
  17.   
  18.     public int getValue() {  
  19.         return value;  
  20.     }  
  21.   
  22.     public void setValue(int value) {  
  23.         this.value = value;  
  24.     }  
  25.   
  26.     public BinaryTreeNode getLeft() {  
  27.         return left;  
  28.     }  
  29.   
  30.     public void setLeft(BinaryTreeNode left) {  
  31.         this.left = left;  
  32.     }  
  33.   
  34.     public BinaryTreeNode getRight() {  
  35.         return right;  
  36.     }  
  37.   
  38.     public void setRight(BinaryTreeNode right) {  
  39.         this.right = right;  
  40.     }  
  41.   
  42. }  

思路:

    如上图所示,在前序遍历的序列中第一个就是树的根结点,此时再在中序遍历的序列里查找这个根结点,则中序遍历的序列里根结点左侧的就是左子树,右侧的就是右子树,再对左右子树进行同样的操作,此时可以使用递归实现,这样便能构造出这个二叉树。

Java代码:

[java] view plain copy
  1. package org.algorithm.pointtooffer;  
  2.   
  3. /** 
  4.  * 面试题6:重建二叉树 
  5.  *  
  6.  * @author dell 
  7.  *  
  8.  */  
  9. public class Item06 {  
  10.     public static void main(String args[]) {  
  11.         // 二叉树的前序遍历  
  12.         int preOrder[] = { 12473568 };  
  13.         // 二叉树的中序遍历  
  14.         int inOrder[] = { 47215386 };  
  15.           
  16.         BinaryTreeNode root = constructTree(preOrder, inOrder);  
  17.         printPostOrder(root);  
  18.     }  
  19.   
  20.     public static BinaryTreeNode constructTree(int preOrder[], int inOrder[]) {  
  21.         // 根据前序遍历创建根结点  
  22.         BinaryTreeNode root = new BinaryTreeNode(preOrder[0]);  
  23.         root.setLeft(null);  
  24.         root.setRight(null);  
  25.   
  26.         int leftNum = 0;//左子树的结点个数  
  27.   
  28.         // 在中序中找到根节点  
  29.         for (int i = 0; i < inOrder.length; i++) {  
  30.             if (inOrder[i] == root.getValue()) {  
  31.                 break;  
  32.             } else {  
  33.                 leftNum++;  
  34.             }  
  35.         }  
  36.         int rightNum = preOrder.length - 1 - leftNum;  
  37.   
  38.         // 左子树不为空  
  39.         if (leftNum > 0) {  
  40.             //构造左子树的前序和中序遍历序列  
  41.             int leftPreOrder[] = new int[leftNum];  
  42.             int leftInOrder[] = new int[leftNum];  
  43.             for (int i = 0; i < leftNum; i++) {  
  44.                 leftPreOrder[i] = preOrder[i + 1];  
  45.                 leftInOrder[i] = inOrder[i];  
  46.             }  
  47.             //递归构造左子树  
  48.             BinaryTreeNode leftRoot = constructTree(leftPreOrder, leftInOrder);  
  49.             root.setLeft(leftRoot);  
  50.         }  
  51.           
  52.         //右子树不为空  
  53.         if (rightNum > 0) {  
  54.             //构造右子树的前序和中序遍历序列  
  55.             int rightPreOrder[] = new int[rightNum];  
  56.             int rightInOrder[] = new int[rightNum];  
  57.             for (int i = 0; i < rightNum; i++) {  
  58.                 rightPreOrder[i] = preOrder[leftNum + i + 1];  
  59.                 rightInOrder[i] = inOrder[leftNum + i + 1];  
  60.             }  
  61.             //递归构造右子树  
  62.             BinaryTreeNode rightRoot = constructTree(rightPreOrder,  
  63.                     rightInOrder);    
  64.             root.setRight(rightRoot);  
  65.         }  
  66.         return root;  
  67.     }  
  68.       
  69.     /** 
  70.      * 二叉树的后序遍历(递归实现) 
  71.      * @param root 树的根结点 
  72.      */  
  73.     public static void printPostOrder(BinaryTreeNode root) {  
  74.         if (root != null) {  
  75.             printPostOrder(root.getLeft());  
  76.             printPostOrder(root.getRight());  
  77.             System.out.print(root.getValue() + "、");  
  78.         }  
  79.     }  
  80. }