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
這道題有很多種問法:
-
由BST構造一個新的無環雙向連結串列。
-
由BST構造一個新的有環雙向連結串列。
-
將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為樹中節點的個數。