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;
}

链表反转之后在打印就方便多了,这里就不在写了。


总结

关于链表的逆序打印应该算是一道比较简单的题了,使用栈,递归,反转都能轻松实现。


在这里插入图片描述

posted @ 2020-09-21 22:36  数据结构和算法  阅读(73)  评论(0编辑  收藏  举报