1. 程式人生 > 實用技巧 >劍指Offer 36.二叉搜尋樹與雙向連結串列

劍指Offer 36.二叉搜尋樹與雙向連結串列

劍指Offer 36.二叉搜尋樹與雙向連結串列

題目

輸入一棵二叉搜尋樹,將該二叉搜尋樹轉換成一個排序的迴圈雙向連結串列。要求不能建立任何新的節點,只能調整樹中節點指標的指向。

為了讓您更好地理解問題,以下面的二叉搜尋樹為例:

我們希望將這個二叉搜尋樹轉化為雙向迴圈連結串列。連結串列中的每個節點都有一個前驅和後繼指標。對於雙向迴圈連結串列,第一個節點的前驅是最後一個節點,最後一個節點的後繼是第一個節點。

下圖展示了上面的二叉搜尋樹轉化成的連結串列。“head” 表示指向連結串列中有最小元素的節點。

特別地,我們希望可以就地完成轉換操作。當轉化完成以後,樹中節點的左指標需要指向前驅,樹中節點的右指標需要指向後繼。還需要返回連結串列中的第一個節點的指標。

解析

最開始我是使用的佇列+中序遍歷的方式來完成二叉搜尋樹轉換為雙向連結串列。這個方式雖然可以完成操作,但是時間複雜度很低,擊敗了16.68%的使用者。哈哈哈。

後來,直接用中序遍歷+pre指標+cur指標來完成轉換。因為直接用遍歷轉換,所以效率比較高。擊敗了100%

解釋一下,思路:

利用precur指標。pre指標是記錄前一個節點,cur指標是記錄當前節點。head指標是記錄頭節點,即第一個節點,方便形成環狀。

還是利用中序遍歷。在操作的時候分兩種情況:

  • pre為null,則表示cur指標指向的是第一個節點,此時就應該將head指標指向第一個節點,記錄下來。
  • pre不為null,則表示有前驅節點,直接按照雙向連結串列規則,確定前驅和後繼指標。然後將pre
    =cur,確定下一個前驅節點。

最佳理解為:畫圖。哈哈哈

解答

/*
// Definition for a Node.
class Node {
    public int val;
    public Node left;
    public Node right;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val,Node _left,Node _right) {
        val = _val;
        left = _left;
        right = _right;
    }
};
*/
class Solution {
    Node pre, head;
    public Node treeToDoublyList(Node root) {
        if(root==null)return null;
        dfs(root);
        head.left = pre;
        pre.right = head;
        return head;
    }

    public void dfs(Node cur){
        if(cur == null) return;
        dfs(cur.left);
        if(pre!=null){
            pre.right = cur;
        }else{
            head = cur;
        }
        cur.left = pre;
        pre = cur;
        dfs(cur.right);
    }
}