1. 程式人生 > 實用技巧 >劍指Offer_#6_從尾到頭列印連結串列

劍指Offer_#6_從尾到頭列印連結串列

劍指Offer_#6_從尾到頭列印連結串列

劍指offer

Contents

題目

輸入一個連結串列的頭節點,從尾到頭反過來返回每個節點的值(用陣列返回)。
示例 1:

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

限制:
0 <= 連結串列長度 <= 10000

思路分析

方法1:輔助棧

遍歷連結串列只能從頭到尾,而這裡需要我們從尾到頭列印連結串列的節點,這可以藉助棧的"先進後出"特點來實現。按照正序將各個節點的值入棧,出棧的時候就是倒序的。

方法2:遞迴

演算法流程

先遍歷到連結串列尾部,然後在回溯的過程中把值新增到結果陣列中。

  1. 終止條件:head == null,即遍歷到連結串列的尾部
  2. 遞推過程:recur(head.next)
  3. 回溯過程:list.add(head)

在遞迴過程中,暫存結果的變數list可以寫成一個類全域性變數,也可以寫成一個遞迴函式的引數,詳見程式碼。

解答

解答1:輔助棧

class Solution {
    public int[] reversePrint(ListNode head) {
        Stack<Integer> stack = new
Stack<>(); while(head != null){ stack.add(head.val); head = head.next; } int[] res = new int[stack.size()]; for(int i = 0;i <= res.length - 1;i++){ res[i] = stack.pop(); } return res; } }

複雜度分析

時間複雜度:O(n)


空間複雜度:O(n)

解答2:遞迴

list做全域性變數

class Solution {
    List<Integer> list = new ArrayList<>();
    public int[] reversePrint(ListNode head) {
        //呼叫遞迴函式
        recur(head);
        //將結果轉換為int陣列
        int[] res = new int[list.size()];
        for(int i = 0;i <= res.length - 1;i++){
            res[i] = list.get(i);
        }
        return res;
    }

    private void recur(ListNode head){
        //終止條件:已經遍歷到連結串列最尾端
        if(head == null) return;
        //遞迴呼叫開始,程式在此被阻塞住,直到滿足終止條件,開始回溯
        recur(head.next);
        //回溯
        list.add(head.val);
    }
}

list做遞迴方法引數

class Solution {
    public int[] reversePrint(ListNode head) {
        List<Integer> list = new ArrayList<>();
        //呼叫遞迴函式
        recur(head, list);
        //將結果轉換為int陣列
        int[] res = new int[list.size()];
        for(int i = 0;i <= res.length - 1;i++){
            res[i] = list.get(i);
        }
        return res;
    }

    private void recur(ListNode head,List<Integer> aList){
        //終止條件:已經遍歷到連結串列最尾端
        if(head == null) return;
        //遞迴呼叫開始,程式在此被阻塞住,直到滿足終止條件,開始回溯
        recur(head.next,aList);
        //回溯
        aList.add(head.val);
    }
}

複雜度分析

時間複雜度:O(n),遞迴函式呼叫n次
空間複雜度:O(n),遞迴呼叫n次,佔用O(n)的棧空間