剑指Offer 06 :从尾到头打印链表
题目描述
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]限制:0 <= 链表长度 <= 10000
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public int[] reversePrint(ListNode head) {
}
}
题目解析
只有头节点的普通链表一般只能够从头至尾依次访问每一个节点,题目要求我们返回一个从尾至头的访问顺序。这种反向操作我们可以考虑:
- 将遍历的结果反向输出
- 利用栈数据结构的先进后出的特点来完成题目要求
题目解法
解法一(遍历结果反向输出):
由链表的头节点可以遍历出整一个链表,在遍历的过程中,我们可以将每一个节点的值存储起来,最后将得到的结果反向遍历
public int[] reversePrint(ListNode head) {
//边界判断
if(head == null) return new int[0];
//新建一个集合存储遍历过程中节点的值
ArrayList<Integer> list = new ArrayList<Integer>();
//遍历链表(当下一个节点为空时(链表到尾)时,打破循环;否则继续遍历)
while(true){
list.add(head.val);
if(head.next == null)
break;
head = head.next;
}
//待返回数组,长度为集合元素个数
int[] res = new int[list.size()];
//遍历集合
int cur = res.length - 1;
for(Integer val : list){
res[cur--] = val;
}
return res;
}
解法二(辅助栈):
要求从尾到头的输出,然而链表只能从头到尾。可以利用栈的先进后出来实现。
public int[] reversePrint(ListNode head) {
if(head == null){
return new int[0];
}
Stack<Integer> stack = new Stack<Integer>();
//记录栈中元素个数
int size = 0;
//遍历链表,将先遍历到的val压入栈中,最后才弹出来
while(true){
//压栈
stack.push(head.val);
size++;
if(head.next == null){
break;
}
head = head.next;
}
int[] res = new int[size];
int cur = 0;
while(!stack.isEmpty()){
//出栈
res[cur++] = stack.pop();
}
return res;
}
解法三(递归):
先进后出的方式可以使用递归实现。
ArrayList<Integer> list = new ArrayList<Integer>();
public int[] reversePrint(ListNode head) {
if(head == null) return new int[0];
funtion(head);
int[] res = new int[list.size()];
for(int i = 0; i < res.length; i++){
res[i] = list.get(i);
}
return res;
}
//往集合中添加当前节点的值,并将下一个节点进行同样操作
private void funtion(ListNode head){
if(head == null)return;
//先后顺序不能弄反
funtion(head.next);
list.add(head.val);
}
心得
明确栈的特性:先进后出
若有类似这种反向操作的题目,可以优先考虑使用栈这个数据结构来解决。