410,剑指 Offer-从尾到头打印链表
想了解更多数据结构以及算法题,可以关注微信公众号“数据结构和算法”,每天一题为你精彩解答。也可以扫描下面的二维码关注
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
限制:
- 0 <= 链表长度 <= 10000
链表节点类
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
使用栈来解决
从尾到头打印链表,首先这个链表是单向的,如果是双向的,直接从后往前打印就行了,这里链表不是单向的。
这里最容易想到的一种方式就是把链表的节点全部压栈,因为栈是先进后出的一种数据结构,全部压栈之后再一个个出栈即可,
压栈完之后再一个个出栈
public int[] reversePrint(ListNode head) {
Stack<ListNode> stack = new Stack<>();
ListNode temp = head;
while (temp != null) {
stack.push(temp);
temp = temp.next;
}
int size = stack.size();
int[] res = new int[size];
for (int i = 0; i < size; i++) {
res[i] = stack.pop().val;
}
return res;
}
递归方式解决
我们知道如果逆序打印一个链表使用递归的方式还是很简单的,像下面这样
public void reversePrint(ListNode head) {
if (head == null)
return;
reversePrint(head.next);
System.out.println(head.val);
}
但这里实际上是要我们返回逆序打印的结果,也就是返回一个数组,所以我们可以改一下
public int[] reversePrint(ListNode head) {
int cout = length(head);
int[] res = new int[cout];
reversePrintHelper(head, res, cout - 1);
return res;
}
//计算链表的长度
public int length(ListNode head) {
int cout = 0;
ListNode dummy = head;
while (dummy != null) {
cout++;
dummy = dummy.next;
}
return cout;
}
public void reversePrintHelper(ListNode head, int[] res, int index) {
if (head == null)
return;
reversePrintHelper(head.next, res, index - 1);
res[index] = head.val;
}
先反转再打印
关于链表的反转其实解法也比较多,这里先列出简单的两种,一个是递归的,一个是非递归的。
递归的方式
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null)
return head;
ListNode tempList = reverseList(head.next);
head.next.next = head;
head.next = null;
return tempList;
}
非递归的方式
public ListNode reverseList(ListNode head) {
ListNode pre = null;
while (head != null) {
ListNode next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
链表反转之后在打印就方便多了,这里就不在写了。
总结
关于链表的逆序打印应该算是一道比较简单的题了,使用栈,递归,反转都能轻松实现。
关注微信公众号“数据结构和算法”,查看更多算法题