面試:用 Java 逆序列印鏈表

來源:互聯網
上載者:User

標籤:簡單   void   代碼   一個棧   並發   block   今天   通過   rev   

昨天的 Java 實現單例模式 中,我們的雙重檢驗鎖機制因為指令重排序問題而引入了 volatile 關鍵字,不少朋友問我,到底為啥要加 volatile 這個關鍵字呀,而它,到底又有什麼神奇的作用呢?

對 volatile 這個關鍵字,在昨天的講解中我們簡單說了一下:被 volatile 修飾的共用變數,都會具有下面兩個屬性:

  • 保證不同線程對該變數操作的記憶體可見度。
  • 禁止指令重排序。

共用變數:如果一個變數在多個線程的工作記憶體中都存在副本,那麼這個變數就是這幾個線程的共用變數。

可見度:一個線程對共用變數值的修改,能夠及時地被其它線程看到。

對於重排序,不熟悉的建議直接 Google 一下,這裡也就不多提了。只需要記住,在多線程中操作一個共用變數的時候,一定要記住加上 volatile 修飾即可。

由於時間關係,我們還是得先進入今天的正題,對於 volatile關鍵字,在要求並發編程能力的面試中還是很容易考察到的,後面我也會簡單給大家講解。

輸入一個單鏈表的頭結點,從尾到頭列印出每個結點的值。

這是《劍指 Offer》上的第五道面試題,鏈表是經常在面試中考察的一種資料結構,所以推薦大家一定要掌握。對於鏈表不熟悉的小夥伴可一定要去《大話資料結構》好好補課喲~

《劍指 Offer》 PDF 版本在公眾號後台回複「劍指Offer」即可擷取。

《大話資料結構》PDF 版本在公眾號後台回複「大話資料結構」即可擷取。

我們的鏈表有很多,單鏈表,雙向鏈表,環鏈表等。這裡是最普通的單鏈表模式,我們一般會在資料存放區地區存放資料,然後有一個指標指向下一個結點。雖然 Java 中沒有指標這個概念,但 Java 的引用恰如其分的填補了這個問題。

看到這道題,我們往往會很快反應到每個結點都有 next 屬性,所以要從頭到尾輸出很簡單。於是我們自然而然就會想到先用一個 while 迴圈取出所有的結點存放到數組中,然後再通過逆序遍曆這個數組,即可實現逆序列印單鏈表的結點值。

我們假定結點的資料為 int 型的。實現代碼如下:

public class Test05 {
    public static class Node {
        int data;
        Node next;
    }

    public static void printLinkReverse(Node head) {
        ArrayList<Node> nodes = new ArrayList<>();
        while (head != null) {
            nodes.add(head);
            head = head.next;
        }
        for (int i = nodes.size() - 1; i >= 0; i--) {
            System.out.print(nodes.get(i).data + " ");
        }
    }

    public static void main(String[] args) {
        Node head = new Node();
        head.data = 1;
        head.next = new Node();
        head.next.data = 2;
        head.next.next = new Node();
        head.next.next.data = 3;
        head.next.next.next = new Node();
        head.next.next.next.data = 4;
        head.next.next.next.next = new Node();
        head.next.next.next.next.data = 5;
        printLinkReverse(head);
    }
}

這樣的方式確實能實現逆序列印鏈表的資料,但明顯用了整整兩次迴圈,時間複雜度為 O(n²)。等等!逆序輸出?似乎有這樣一個資料結構可以完美解決這個問題,這個資料結構就是棧。

棧是一種「後進先出」的資料結構,用棧的原理更好能達到我們的要求,於是實現代碼如下:

public class Test05 {
    public static class Node {
        int data;
        Node next;
    }

    public static void printLinkReverse(Node head) {
        Stack<Node> stack = new Stack<>();
        while (head != null) {
            stack.push(head);
            head = head.next;
        }
        while (!stack.isEmpty()) {
            System.out.print(stack.pop().data + " ");
        }
    }

    public static void main(String[] args) {
        Node head = new Node();
        head.data = 1;
        head.next = new Node();
        head.next.data = 2;
        head.next.next = new Node();
        head.next.next.data = 3;
        head.next.next.next = new Node();
        head.next.next.next.data = 4;
        head.next.next.next.next = new Node();
        head.next.next.next.next.data = 5;
        printLinkReverse(head);
    }
}

既然可以用棧來實現,我們也極容易想到遞迴也能解決這個問題,因為遞迴本質上也就是一個棧結構。要實現逆序輸出鏈表,我們每訪問一個結點的時候,我們先遞迴輸出它後面的結點,再輸出該結點本身,這樣鏈表的輸出結果自然也是反過來了。

代碼如下:

public class Test05 {
    public static class Node {
        int data;
        Node next;
    }

    public static void printLinkReverse(Node head) {
        if (head != null) {
            printLinkReverse(head.next);
            System.out.print(head.data+" ");
        }
    }

    public static void main(String[] args) {
        Node head = new Node();
        head.data = 1;
        head.next = new Node();
        head.next.data = 2;
        head.next.next = new Node();
        head.next.next.data = 3;
        head.next.next.next = new Node();
        head.next.next.next.data = 4;
        head.next.next.next.next = new Node();
        head.next.next.next.next.data = 5;
        printLinkReverse(head);
    }
}

雖然遞迴代碼看起來確實很整潔,但有個問題:當鏈表非常長的時候,一定會導致函數調用的層級很深,從而有可能導致函數調用棧溢出。所以顯示用棧基於迴圈實現的代碼,健壯性還是要好一些的。

好了,今天的面試講解就到這,我們明天再見!

面試:用 Java 逆序列印鏈表

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.