目录

11、剑指 Offer 06. 从尾到头打印链表

一、题目

剑指 Offer 06. 从尾到头打印链表 难度简单

输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。

示例 1:

输入:head = [1,3,2]
输出:[2,3,1]

限制:

0 <= 链表长度 <= 10000

二、解法

2.1、辅助栈

核心思想:

栈的特点是后进先出,即最后压入栈的元素最先弹出。考虑到栈的这一特点,使用栈将链表元素顺序倒置。从链表的头节点开始,依次将每个节点的值压入栈内,然后依次弹出栈内的元素并存储到数组中。

复杂度分析:

时间复杂度:O(n)。正向遍历一遍链表,然后从栈弹出全部节点,等于又反向遍历一遍链表。

空间复杂度:O(n)。额外使用一个栈存储链表中的每个节点。

代码:

class Solution {
    public int[] reversePrint(ListNode head) {
        Stack<Integer> stack = new Stack<>();

        // 遍历链表, 入栈
        while (head != null) {
            stack.push(head.val);
            head = head.next;
        }

        int[] result = new int[stack.size()];

        // 循环出栈,构造数据
        for (int i = 0; i < result.length; i++) {
            result[i] = stack.pop();
        }

        return result;
    }
}

2.1、递归法

核心思想:

利用递归: 先走至链表末端,回溯时依次将节点值加入列表 ,这样就可以实现链表值的倒序输出。

  • 递推阶段: 每次传入 head.next ,以 head == null(即走过链表尾部节点)为递归终止条件,此时直接返回。
  • 回溯阶段: 层层回溯时,将当前节点值加入列表,即tmp.add(head.val)
  • 最终,将列表 tmp 转化为数组 res ,并返回即可。

复杂度分析:

时间复杂度:O(N),遍历链表,递归 N 次。

空间复杂度:O(N), 系统递归需要使用 O(N) 的栈空间。

代码:

class Solution {
    ArrayList<Integer> arrayList = new ArrayList<>();

    public int[] reversePrint(ListNode head) {
        // 边界值
        if (head == null) {
            return new int[]{};
        }

        reverse(head);

        int[] result = new int[arrayList.size()];

        for (int i = 0; i < arrayList.size(); i++) {
            result[i] = arrayList.get(i);
        }

        return result;
    }

    // 在递归遍历链表的回溯过程中利用 ArrayList 记录数据, 天然就是逆序的
    public void reverse(ListNode node) {
        if (node.next == null) {
            arrayList.add(node.val);
            return;
        }

        // 递归调用
        reverse(node.next);

        // 回溯阶段
        arrayList.add(node.val);
    }
}

REF

https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/solution/mian-shi-ti-06-cong-wei-dao-tou-da-yin-lian-biao-b/