1. 程式人生 > >LeetCode426 將二叉搜尋樹轉化為排序的雙向連結串列

LeetCode426 將二叉搜尋樹轉化為排序的雙向連結串列

Question:

Convert a binary search tree to doubly linked list with in-order traversal.

Example:

Given a binary search tree:

4

/
2 5
/
1 3
return 1<->2<->3<->4<->5
這道題有很多種問法:

  1. 由BST構造一個新的無環雙向連結串列。

  2. 由BST構造一個新的有環雙向連結串列。

  3. 將BST改造成一個雙向連結串列。

問題1:中序遍歷BST,每訪問一個新的tree node,構造一個新的list node。將新的list node的prev指標指向之前訪問的list node,然後將之前訪問的list node的next指標指向新的list node。因為要記錄之前訪問的list node的資訊,我們建立一個state物件,state.prev記錄之前訪問的list node,state.head記錄連結串列的頭節點。如何判斷頭節點很簡單,如果state.prev等於null,說明當前節點之前沒有節點了,那麼該節點就是頭節點。helper函式的定義:以root為根節點的BST構造一個雙向連結串列,並將新連結串列連結到state.prev節點上去,同時記錄頭節點和最後訪問的節點的資訊。

問題2:在問題1的基礎上,每往連結串列中新增一個新節點,將頭節點的prev指標指向該新節點,然後新節點的next指標指向頭節點。當連結串列構造完,整個連結串列自然就是一個迴圈連結串列。

問題3:和之前的問題幾乎一模一樣,因為tree node有兩個指標(left,right),list node同樣有兩個指標(prev,next)。遍歷BST的時候,每訪問一個tree node,將它的left指標指向之前訪問的tree node,將之前訪問的tree node的right指標指向當前節點。注意:不可以修改當前訪問的tree node的right指標,因為我們需要通過right指標找到下一個訪問的tree node。

non-cycle:

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 * Definition for Doubly-ListNode.
 * public class DoublyListNode {
 *     int val;
 *     DoublyListNode next, prev;
 *     DoublyListNode(int val) {
 *         this.val = val;
 *         this.next = this.prev = null;
 *     }
 * }
 */

//用來記錄list的狀態,prev是之前訪問的node,head是第一個node
class State {
    DoublyListNode prev;
    DoublyListNode head;
    
    State(DoublyListNode prev, DoublyListNode head) {
        this.prev = prev;
        this.head = head;
    }
    
    State() {
        this.prev = null;
        this.head = null;
    }
}

// 每次新建一個節點,將它指向前一個節點,前一個節點指向它
public class Solution {
    /**
     * @param root: The root of tree
     * @return: the head of doubly list node
     */
    public DoublyListNode bstToDoublyList(TreeNode root) {  
        if(root == null) {
            return null;
        }
        
        // DoublyListNode prev = null, head = null;
        State state = new State();
        helper(root, state);
        
        return state.head;
    }
    
    //helper函式的定義是:將root為根的樹變成doubly-linked list然後與state.prev相連線
    private void helper(TreeNode root, State state) {
        if(root == null) {
            return;
        }
        
        helper(root.left, state);
        
        DoublyListNode node = new DoublyListNode(root.val);
        node.prev = state.prev;
        if(state.prev != null) {
            state.prev.next = node;
        }else {
            state.head = node;
        }
        
        state.prev = node;
        helper(root.right, state);
    }
}

cycle:

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 * Definition for Doubly-ListNode.
 * public class DoublyListNode {
 *     int val;
 *     DoublyListNode next, prev;
 *     DoublyListNode(int val) {
 *         this.val = val;
 *         this.next = this.prev = null;
 *     }
 * }
 */

//用來記錄list的狀態,prev是之前訪問的node,head是第一個node
class State {
    DoublyListNode prev;
    DoublyListNode head;
    
    State(DoublyListNode prev, DoublyListNode head) {
        this.prev = prev;
        this.head = head;
    }
    
    State() {
        this.prev = null;
        this.head = null;
    }
}

// 每次新建一個節點,將它指向前一個節點,前一個節點指向它
public class Solution {
    /**
     * @param root: The root of tree
     * @return: the head of doubly list node
     */
    public DoublyListNode bstToDoublyList(TreeNode root) {  
        if(root == null) {
            return null;
        }
        
        // DoublyListNode prev = null, head = null;
        State state = new State();
        helper(root, state);
        
        return state.head;
    }
    
    private void helper(TreeNode root, State state) {
        if(root == null) {
            return;
        }
        
        helper(root.left, state);
        
        DoublyListNode node = new DoublyListNode(root.val);
        node.prev = state.prev;
        if(state.prev != null) {
            state.prev.next = node;
        }else {
            state.head = node;
        }
        
        state.head.prev = node;
        node.next = state.head;
        state.prev = node;
        helper(root.right, state);
    }
}

時間複雜度為O(n),n為樹中節點的個數。