6.从尾到头打印链表
题目描述
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
解题思路
链表从头到尾先添加一个ArrayList,再反转这个操作,复杂度高。直接翻转链表高效。
import java.util.ArrayList;
public class Solution {
public static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
// 基础解法
ArrayList<Integer> array = new ArrayList<Integer>();
ListNode p = listNode;
while (p!=null){
array.add(p.val);
p = p.next;
}
ArrayList<Integer> array2 = new ArrayList<Integer>();
for (int i=array.size()-1;i>-1;i--){
array2.add(array.get(i));
}
return array2;
}
public ArrayList<Integer> printListFromTailToHead2(ListNode listNode) {
// 尝试降低空间复杂度,翻转链表
ArrayList<Integer> array = new ArrayList<Integer>();
if(listNode==null){
return array;
}
ListNode p = listNode;
listNode = listNode.next;
ListNode next = listNode;
p.next = null;
while (listNode!=null){
listNode = listNode.next;
next.next=p;
p = next;
next = listNode;
}
while (p!=null){
array.add(p.val);
p = p.next;
}
return array;
}
}
7.重建二叉树
题目描述
根据二叉树的前序遍历和中序遍历的结果,重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
解题思路
这道题的思路考研的时候是知道,但是实现起来,不太熟悉递归的坑,容易被树根的判断卡住。解题思路主要是使用前序第一个数作为根节点,然后找到该节点在中序中的位置,该位置左侧的数都是左子树的节点,右侧都是右子树的节点。根据左右子树节点的数量,在前序中根节点的后边取同样数量的数目即可区分左右子树,递归求解即可。
import java.util.Arrays;
public class Solution {
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
}
// 重建二叉树
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
TreeNode t = null;
if (in.length == 0){
}else if(in.length == 1){
t = new TreeNode(pre[0]);
}else if (in.length != 0){
t = new TreeNode(pre[0]);
// 找到pre第一个值对应的in的序号
int id = 0;
for (int i=0;i<in.length;i++)
if (in[i] == pre[0])
id = i;
int[] in_left = Arrays.copyOfRange(in, 0, id);
int[] in_right = Arrays.copyOfRange(in, id+1, in.length);
int[] pre_left = Arrays.copyOfRange(pre, 1,1+in_left.length);
int[] pre_right = Arrays.copyOfRange(pre, 1+in_left.length,pre.length);
// pre的长度总是和in的长度相等
TreeNode left = reConstructBinaryTree(pre_left, in_left);
TreeNode right = reConstructBinaryTree(pre_right, in_right);
t.left = left;
t.right = right;
}
return t;
}
}
8.二叉树的下一个结点
题目描述
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
解题思路
中序遍历的下一个结点有如下特征,是该结点的右子树的最左子树或其第一个右指向的祖先节点。以下是两个版本的解法,牛客没有该题。
public class Solution {
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode parent;
TreeNode(int x) {
val = x;
}
}
public TreeNode findnextnode(TreeNode t){
TreeNode p = t.right;
if(p != null){
p = findleftcild(p);
}
else {
p = findrightparent(t.parent);
}
return p;
}
private TreeNode findleftcild(TreeNode t){
if(t.left != null){
t = findleftcild(t.left);
}
return t;
}
private TreeNode findrightparent(TreeNode t){
if(t.parent.left != t){
t = t.parent;
}
return t;
}
// 牛客看到的解法
public TreeNode GetNext(TreeNode pNode) {
if (pNode.right != null) {
TreeNode node = pNode.right;
while (node.left != null)
node = node.left;
return node;
} else {
while (pNode.parent != null) {
TreeNode parent = pNode.parent;
if (parent.left == pNode)
return parent;
pNode = pNode.parent;
}
}
return null;
}
}
9.用两个栈实现队列
题目描述
用两个栈来实现一个队列,完成队列的 Push 和 Pop 操作。
解题思路
使用stack1作为存储对象,入队和入栈的操作一致,出队时需要将stack1所有值出栈,按顺序入栈stack2,这样即可实现反转,将stack2栈首出栈,其余元素再倒序回stack1即可完成队列操作。
import java.util.Stack;
public class Solution9 {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack1.empty())
return 0;
while (!stack1.empty()){
stack2.push(stack1.pop());
}
int popnum = stack2.pop();
while (!stack2.empty()){
stack1.push(stack2.pop());
}
return popnum;
}
}