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

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。

题目描述(level 简单)

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

给定已经定义好的链表结构ListNode如下

public class ListNode {
   private int val;
   private ListNode next;
   public ListNode(int x) {
      val = x;
   }
}
示例
输入:head = [1,3,2]
输出:[2,3,1]
思路分析LeetCode(辅助栈)

单链表的结构特点,当前节点指向下数据结构教程第5版李春葆答案一个节点的引用,只能从前往后访问每一个节点。根据题目要求从尾部打印链表,那么第一反应就是“反转”链表然后打印输出即可。倒序打印说白了就是先入后出嘛,很明显天然就是先入后出的数据结构。可以考虑链表使用一个辅助数组公式栈,在遍历链表的同时数组公式将数据压栈,最后出栈即可。

代码实现leetcode分割互斥(辅助栈)
class Solution {
    public int[] reversePrint(ListNode head) {
       Stack<ListNode> stack = new Stack<>();
       ListNode temp = head;
       while (null != temp) {
           stack.push(temp);
           temp = temp.next;
       }
       int size = stack.size();
       int[] print = new int[size];
       for (int i = 0; i < size; i++) {
           print[i] = stack.pop().val;
       }
       return print;
    }
}
思路分析(递归)

链表的遍历leetcode刷题网站特点,最后一个节点指向null,这是一个很明显的特征数组排序。一般我们在写递归调用时,都会有一个出口,这里的出口就已经很明确了。但是不仅仅是自己,发现很多同行都有点排斥链表和数组的区别归。究其原因,大概是觉得写起来很别扭,不太符合人的思维方式,但是自认为,递归思想才是“真正是站在计算机的角度思考问题”。回到正题,从尾打印链表,使用递归思想,递归分为两个过程:递推阶段回溯阶段;递推阶段的出口已经找到了,随着遍历的进行当head == null时,递推阶段结束,接着层层回溯,此时我们只要将链表和数组的区别对应的节点的值添加到一个数组中即可(倒序),最后返回这个临时数组并打印。

代码实现(递归)
class Solution {
    int m = 0, n = 0;
    int[] result;
    public int[] reversePrint(ListNode head) {
        recursion(head);
        return result;
    }
    public void recursion(ListNode head) {
        if (null == head) {
            result = new int[m];
            return;
        }
        m++;
        recursion(head.next);
        result[n] = head.val;
        n++;
    }
}
//其中m、n分别表示数组的容量,与对应value的下标
时间复杂度
  • 辅助栈

时间复杂度为O(N):包含遍历链表与栈的入栈出栈操作。

空间复杂度为O(N):引入辅助栈,数组。

  • 递归

时间复杂度为O(N):遍历整个链表。

空间复杂链表反转O(N):递归深度与链表大小相关。

链接

Leet数组去重Code