输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
- 题解一:
单向链表,从头往尾遍历,但是需要从尾到头打印,自然想到栈,遍历链表添加进栈里面,然后一个一个的出栈。
/*运行时间:14ms
占用内存:9572k*/
public ArrayList<Integer> printListFromTailToHead02(ListNode listNode) {
if (null == listNode) {
return new ArrayList<Integer>();
}
Stack<Integer> stack = new Stack<>();
ListNode p = listNode;
while (null != p){
stack.push(p.val);
p = p.next;
}
int size = stack.size();
res = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
res.add(stack.pop());
}
return res;
}
- 题解二:
既然想到了用栈来实现这个函数,而递归在本质上就是一个栈结构,于是很自然的又想到了用递归来实现。要实现返回来输出链表,我们每访问到一个节点的时候,先递归输出它后面的节点,再输出该节点自身,这样链表的输出结果就反过来了。
private ArrayList<Integer> res;
/*运行时间:16ms
占用内存:9424k*/
public ArrayList<Integer> printListFromTailToHead01(ListNode listNode) {
if (null == listNode) {
return new ArrayList<Integer>();
}
recursion(listNode, 1);
return res;
}
public void recursion(ListNode listNode, int n) {
if (listNode.next == null) {
res = new ArrayList(n);
res.add(listNode.val);
return;
}
recursion(listNode.next, n + 1);
res.add(listNode.val);
}
总结:递归的代码看起来很简洁,但有一个问题:当链表非常长的时候,就会导致函数调用的层级很深,从而有可能导致函数调用栈溢出。显然基于循环实现的栈的代码的鲁棒性要好一些。