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

123 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

题目:给定一个链表的头节点,要求用数组返回链表的倒序。

例如:

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

解题思路

因为栈具有先进后出的特性,因此根据本题要求,我们可以将链表元素从前往后入栈,之后依次出栈保存至结果数组中即可,代码如下:

public static int[] reversePrint(ListNode head){
    Stack<Integer> stack = new Stack<>();
    while(head!=null){
        stack.push(head.val);
        head = head.next;
    }
    int size = stack.size();
    int[] result = new int[size];
    for(int i=0;i<size;i++){
        result[i] = stack.pop();
    }
    return result;
}

时间复杂度和 空间复杂度都是O(n)O(n)

上面的方法用到了栈,因为只需要将结果保存至数组中,我们是否可以直接遍历链表将结果倒序存入结果数组,这样栈的空间复杂度就不需要了,代码如下:

public int[] reversePrint(ListNode head){
    int len = 0;
    ListNode temp = head;
    while(temp!=null){
        len++;
        temp = temp.next;
    }

    int[] result = new int[len];
    for(int i=len-1;i>=0;i--){
        result[i] = head.val;
        head = head.next;
    }

    return result;
}

这样如果不算输出数组的空间复杂度,最终空间复杂度就是O(1)O(1)

本题算是做出来了,但是想象一下,本题是否还是链表逆序的变体,在此处复习一下链表倒序:

链表倒序可使用递归和非递归两种方式解决,下面一一展示:

  • 非递归:非递归方式很简单,实现定义一个空节点,之后使用头插法的方式将节点插入空节点之后即可,最终的逆序就是空节点.next。用此思路解决本题代码如下:

    public int[] reversePrint(ListNode head){
        if(head == null) return new int[0];
        ArrayList<Integer> list = new ArrayList<>();
        ListNode headPoint = new ListNode(-1);
    
        while(head!=null){
            ListNode tempNode = head.next;
            head.next = headPoint.next;
            headPoint.next = head;
            head = tempNode;
        }
    
        while(headPoint.next!=null){
            list.add(headPoint.next.val);
            headPoint = headPoint.next;
        }
    
        return list.stream().mapToInt(Integer::valueOf).toArray();
    }
    

    最终耗时3ms,和上面差距有点大。

  • 递归:递归的方式很巧妙,我们需要注意当遍历到最后一个节点时,我们就需要将链表进行返回,而不能继续遍历下去,具体代码如下:

    public int[] reversePrint(ListNode head){
        if(head == null) return new int[0];
        ArrayList<Integer> list = new ArrayList<>();
        head = reverseList(head);
        while(head!=null){
            list.add(head.val);
            head = head.next;
        }
        return list.stream().mapToInt(Integer::valueOf).toArray();
    }
    
    public static ListNode reverseList(ListNode head){
        if(head == null || head.next == null) return head;
        ListNode p = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return p;
    }
    

    最终耗时也是3ms。但这两种思路是必须掌握的!