面试题6:输入一个链表的头结点,从尾到头反过来打印出每个节点的值。
利用堆栈的数据结构,将数据先存进堆里面,然后遍历堆,取出堆里面的元素放进ArrayList里面
/**这种结构铁定不是java1.8版本的,因为1.8版本的ListNode结构就直接是List<Node>,每个值是一个Node节点,并不能直接得到int val,还是说这种结构是自定义的数字链表结构?
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if(listNode == null){
ArrayList list = new ArrayList();
return list;
}
Stack<Integer> stk = new Stack<Integer>();
while(listNode != null){
stk.push(listNode.val);
listNode = listNode.next;
}
ArrayList<Integer> arr = new ArrayList<Integer>();
while(!stk.isEmpty()){
arr.add(stk.pop());
}
return arr;
}
}
简洁版的递归实现:
public class Solution{
ArrayList<Integer> arrayList=new ArrayList<Integer>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if(listNode != null){
printListFromTailToHead(listNode.next);
arrayList.add(listNode.val)
}
return arrayList;
}
}
按照java 1.8版本提供的ListNode实现:
package javaOffer;
import org.jruby.ast.ListNode;
import org.jruby.ast.Node;
import java.util.ArrayList;
import java.util.Stack;
/**
* Created by 罗浩 on 2018/1/28.
*/
public class Solution6{
public ArrayList<Node> printListFromTailToHead(ListNode listNode) {
ArrayList<Node> arrayList = new ArrayList<>();
Stack<Node> stack = new Stack<>();//栈这里的实现应该用LinkedList用错了
for ( int i = 0; i < listNode.size() ; i++) {
stack.push(listNode.get(i));
}
if (!stack.isEmpty()) {
arrayList.add(stack.pop());
}
return arrayList;
}
}
**面试题7:重建二叉树
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历中都不会出现相同的数字。**
基础知识回顾:
前序遍历:先依次打印父节点的值直到没有左子树,然后递归遍历父节点的右子树
中序遍历:从二叉树的最左子树开始打印,然后打印父节点值,在递归遍历父节点的右子树
后序遍历:先从二叉树的最左子树开始打印,然后递归遍历右子树,再打印父节点的值。
思路:根据前序序列的值将中序遍历分为左边左子树右边右子树两部分,同时根据已经分好的两部分把前序遍历也分成两部分分别作为再分的子前序序列,然后一直重复分下去。
前序遍历:{1,2,4,7,3,5,6,8}
中序遍历:{4,7,2,1,5,3,8,6}
根据前序遍历的1(root节点) 将中序遍历分为左子树{4,7,2}和右子树{5,3,8,6},然后前序遍历分为左子树前序遍历{2,4,7}和右子树前序遍历{3,5,6,8};在所分的左子树二叉树递归获取root.left,左子树递归完了从右子树部分获取root.right
代码实现:
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
return root;
}
//前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
private TreeNode reConstructBinaryTree(int [] pre,int startPre,int endPre,int [] in,int startIn,int endIn) {
if(startPre>endPre||startIn>endIn)
return null;
TreeNode root=new TreeNode(pre[startPre]);
for(int i=startIn;i<=endIn;i++)
if(in[i]==pre[startPre]){
root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);
root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);
}
return root;
}
}
面试题8:二叉树的下一个节点
题目:给定某一个二叉树和其中的一个节点,如何找出中序遍历的下一个节点?树中的节点除了有两个分别指向左、右的引用,还有指向其父节点的引用
思路分析:首先熟悉二叉树的中序遍历,不然没法分析清楚。从两种情况分析:
给出的节点有右子树:找第一个当前节点是父节点左孩子的节点,直到找到根节点 返回null(所给节点是最右叶子结点)
/*
public class TreeLinkNode {
int val;
TreeLinkNode left = null;
TreeLinkNode right = null;
TreeLinkNode next = null;
TreeLinkNode(int val) {
this.val = val;
}
}
*/
public class Solution {
TreeLinkNode GetNext(TreeLinkNode node)
{
if(node==null) return null;
if(node.right!=null){ //如果有右子树,则找右子树的最左节点
node = node.right;
while(node.left!=null) node = node.left;
return node;
}
while(node.next!=null){ //没右子树,则找第一个当前节点是父节点左孩子的节点
if(node.next.left==node) return node.next;
node = node.next;
}
return null; //退到了根节点仍没找到,则返回null
}
}