面试题6:从尾到头打印链表
题目描述
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList
思路
- 先进后出:栈结构, LinkedList可以实现栈数据结构
- 稍微注意一下泛型问题
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
第三次做; 递归版, 空间幅度高一些, 毕竟使用了系统栈; 要理清楚递归逻辑, 递归逻辑要能够体现:1)新条件新递归 2)当前条件
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
//递归版
ArrayList<Integer> al = new ArrayList<>();
core(al, listNode);
return al;
}
//递归函数逻辑: 把head之后的节点的val都加入al后(新条件新递归), 再把head的val加入al(当前条件)
private void core(ArrayList<Integer> al, ListNode head){
//base case
if(head==null)
return;
//新条件新递归
core(al, head.next);
//当前条件
al.add(head.val);
}
}
第三次做; 反转链表法的时间复杂度是O(N), 空间复杂度是O(1)
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> al = new ArrayList<>();
if(listNode==null)
return al;
ListNode left=null, cur=listNode, right;
while(cur!=null){
//save
right = cur.next;
//change
cur.next = left;
//update
left = cur;
cur = right;
}
//还原
cur = left;
right = null;
while(cur!=null){
//save
left = cur.next;
//update al
al.add(cur.val);
//change
cur.next = right;
//update
right = cur;
cur = left;
}
return al;
}
}
第二次做, 递归版, 此递归含义的理解:先把i+1,…,last的val加入res,再把i的val加入res;递归函数的处理逻辑并没有使用到return的结果, 这个return是返回给外部的
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> res = new ArrayList<>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
//base case
if(listNode == null)
return res;
//先把i+1,...last的val加入res
printListFromTailToHead(listNode.next);
//再把i的val加入res
res.add(listNode.val);
return res; //递归函数的处理逻辑并没有使用到return的结果, 这个return是返回给外部的
}
}
第二次做, 空间复杂度为O(1)的解法, 反转链表法
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
//空间复杂度O(1)的解法
ArrayList<Integer> res = new ArrayList<>();
if(listNode==null)
return res;
ListNode left=null, curr=listNode, right=null;
//reverse linkedlist
while(curr!=null){
//save next node
right = curr.next;
//chage direction
curr.next = left;
//update pointer\
left = curr;
curr = right;
}
curr = left;
while(left!=null){
res.add(left.val);
left = left.next;
}
//restore linkedlist
while(curr!=null){
left = curr.next;
//
curr.next = right;
//
right = curr;
curr = left;
}
return res;
}
}
import java.util.ArrayList;
import java.util.LinkedList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
// 健壮性判断. 加上下面这个健壮性判断就错了!
//if(listNode == null)
//return null;
// 开始处理
LinkedList<Integer> ll = new LinkedList();
while(listNode != null){
ll.addFirst(listNode.val);
listNode = listNode.next;
}
ArrayList<Integer> al = new ArrayList();
while(!ll.isEmpty()){
al.add(ll.remove());
}
return al;
}
}
使用栈
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> al = new ArrayList<>();
if(listNode==null) return al;
Stack<Integer> s = new Stack<>();
while(listNode!=null){
s.push(listNode.val); //直接压入数值,而不是节点,会省点空间
listNode = listNode.next;
}
while(!s.isEmpty())
al.add(s.pop());
return al;
}
}
递归版
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
//input check
ArrayList<Integer> al = new ArrayList<>();
if(listNode==null) return al;
Core(listNode, al);
return al;
}
public void Core(ListNode listNode, ArrayList<Integer> al){
if(listNode==null) return;
Core(listNode.next,al);
al.add(listNode.val);
}
}
递归版(简洁)
import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> al = new ArrayList<>();
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
if(listNode == null) return al;
printListFromTailToHead(listNode.next);
al.add(listNode.val);
return al;
}
}