面试题6:从尾到头打印链表

- 要求返回的结果是动态数组,而且元素是链表中结点值从尾到头的顺序。
- 巧借
ArrayList.add(0, element)方法,在顺序遍历链表时将结点值逆序存入数组中。
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> result = new ArrayList<>();
while (listNode != null) {
// 采用头插法,使得最后为逆序
result.add(0, listNode.val);
// listNode指向下一个结点
listNode = listNode.next;
}
return result;
}
面试题7:重建二叉树


- 二叉树的前序遍历,第一个节点为根节点。找到中序遍历中对应的根节点,可以将中序数组分为左右子树。

- 根据中序遍历中得到左右子树,可以得到前序遍历中的左右子树。

- 先构建根节点,然后分别根据左子树的中序、前序数组和右子树的中序、前序数组,递归构建左右子树。
- 特殊情况: 如果前序序列或中序序列长度为0,直接返回
null。 - 代码如下,其中获得左右子树的数组使用
System.arraycopy()方法去完成。System.arraycopy()是native方法。
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
if (pre.length == 0 || in.length == 0) {
return null;
}
int index = 0; // 标记中序中的根节点位置
for (; index < in.length; index++) {
if (in[index] == pre[0]) {
break;
}
}
TreeNode root = new TreeNode(pre[0]);
// 获得左子树的前序、中序数组
int[] leftPre = new int[index];
System.arraycopy(pre, 1, leftPre, 0, index);
int[] leftIn = new int[index];
System.arraycopy(in, 0, leftIn, 0, index);
// 根据左子树的前序、中序数组,递归构造左子树
root.left = reConstructBinaryTree(leftPre, leftIn);
int rightLen = pre.length - index - 1;
int[] rightPre = new int[rightLen];
System.arraycopy(pre, index + 1, rightPre, 0, rightLen);
int[] rightIn = new int[rightLen];
System.arraycopy(in, index + 1, rightIn, 0, rightLen);
root.right = reConstructBinaryTree(rightPre, rightIn);
return root;
}
leetcode:根据中序和后续序列构建二叉树
- 后序序列中,最后一个值为根节点。根据后序序列中的根节点,可以将中序序列分为左右子树。
- 根据中序序列中,左右子树的长度,可以将后续序列从左到右分为左右子树。
- 获得了左右子树的中序、后序序列,便可以递归构建左右子树。
- 代码如下:
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder.length == 0 || postorder.length == 0) {
return null;
}
int index = 0;// 标记中序序列中根节点的位置
int len = inorder.length;
for (; index < len; index++) {
if (inorder[index] == postorder[len - 1]) {
break;
}
}
TreeNode root = new TreeNode(postorder[len - 1]);
// 获得左子树的中序、后序序列
int[] leftIn = new int[index];
System.arraycopy(inorder, 0, leftIn, 0, index);
int[] leftPost = new int[index];
System.arraycopy(postorder, 0, leftPost, 0, index);
root.left = buildTree(leftIn, leftPost);
int rightLen = len - index - 1;
int[] rightIn = new int[rightLen];
System.arraycopy(inorder, index + 1, rightIn, 0, rightLen);
int[] rightPost = new int[rightLen];
System.arraycopy(postorder, index, rightPost, 0, rightLen);
root.right=buildTree(rightIn,rightPost);
return root;
}
面试题8:二叉树的下一个节点


- 有三种情况:
- 目标节点有右子树,则下一个将要访问的节点是右子树中最左子节点。如节点
b,下一次将要访问的是其右子树中的节点h。 - 如果目标节点是其父节点的左孩子且自身没有右子树,则它的父节点就是下一个将要访问的节点。如节点
d,下一个将要访问的是节点b。 - 如果目标节点是其父节点的右孩子且没有右子树,则需要向上查找其父节点。如果该父节点是爷爷的左孩子,则下一次将要访问的就是爷爷节点。如节点
i,下一次将要访问的是节点a。 - 其他情况都返回
null,如根节点没有右子树,则下一个将要访问的节点为null。
- 其中第2和第3种情况可以合并为一种情况:当目标节点没有右子树时,向上查找其父节点并不断更新指向目标节点的引用,直到当前节点是其父节点的左孩子。
- 代码如下:
public TreeLinkNode GetNext(TreeLinkNode pNode) {
// 右子树不为空,查找右子树的最左节点
if (pNode.right != null) {
TreeLinkNode cur = pNode.right;
while (cur.left != null) {
cur = cur.left;
}
return cur;
}else {
// 右子树为空,如果存在下一个访问的节点,则该节点一定是自己父节点的左孩子
while (pNode.next!=null){
TreeLinkNode parent=pNode.next;
if (parent.left==pNode){
return parent;
}
pNode=parent;
}
}
return null;
}
面试题9:用两个栈实现队列

- 对应的leetcode232:Implement Queue using Stacks
- 使用两个栈模拟队列:
- 删除元素,总是从
stack2中删除。 如果stack2不为空,直接执行pop()操作;如果stack2为空,需要先将stack1中的元素压入stack1中,在对stack2执行pop()操作。 - 添加元素,总是向
stack1中添加。

- 代码如下:
import java.util.Stack;
public class MyQueue {
private Stack<Integer> stack1;
private Stack<Integer> stack2;
/**
* Initialize your data structure here.
*/
public MyQueue() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
/**
* Push element x to the back of queue.
*/
public void push(int x) {
stack1.push(x);
}
/**
* Removes the element from in front of queue and returns that element.
*/
public int pop() {
if (stack2.isEmpty()) {
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
/**
* Get the front element.
*/
public int peek() {
if (stack2.isEmpty()) {
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
return stack2.peek();
}
/**
* Returns whether the queue is empty.
*/
public boolean empty() {
if (stack2.isEmpty() && stack1.isEmpty()) {
return true;
}
return false;
}
}
相似题:leetcode:Implement Stack using Queues
- 使用两个队列模拟栈:
- 针对push操作: 如果两个队列都为空,直接添加到queue1中;如果queue1非空,将元素添加到queue1的末尾;否则,添加到queue2的末尾。
- 针对pop操作: 如果queue1非空,删除queue1的末尾元素,并将queue1中的元素移动到queue2中;如果queue2非空,删除queue2中末尾的元素,将queue2中的元素移动到queue1中。
- 针对top操作: 如果queue1非空,则获取queue1的末尾元素;如果queue2非空,则获取queue2的末尾元素。
- 针对isEmpty操作: 直接判断queue1和queue2是否均为空。

- 代码如下:
import java.util.LinkedList;
public class MyStack {
private LinkedList<Integer> queue1;
private LinkedList<Integer> queue2;
/**
* Initialize your data structure here.
*/
public MyStack() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
/**
* Push element x onto stack.
*/
public void push(int x) {
if (queue1.isEmpty() && queue2.isEmpty()) {
queue1.add(x);
} else if (!queue1.isEmpty()) {
queue1.addLast(x);
} else {
queue2.addLast(x);
}
}
/**
* Removes the element on top of the stack and returns that element.
*/
public int pop() {
int val = 0;
if (!queue1.isEmpty()) {
val = queue1.removeLast();
while (!queue1.isEmpty()) {
queue2.addLast(queue1.removeFirst());
}
} else {
val = queue2.removeLast();
while (!queue2.isEmpty()) {
queue1.addLast(queue2.removeFirst());
}
}
return val;
}
/**
* Get the top element.
*/
public int top() {
if (!queue1.isEmpty()) {
return queue1.getLast();
} else {
return queue2.getLast();
}
}
/**
* Returns whether the stack is empty.
*/
public boolean empty() {
if (queue2.isEmpty() && queue1.isEmpty()) {
return true;
}
return false;
}
}
本文深入解析了链表与二叉树相关的经典面试题目,包括从尾到头打印链表、重建二叉树、二叉树的下一个节点等,详细介绍了算法思路与实现代码。

11万+

被折叠的 条评论
为什么被折叠?



