題目:
給定一個升序排列的有序單鏈表,將其轉換為一棵平衡的二叉搜尋樹。
分析:單鏈表的結點結構如下。
struct node { int data; struct node *next;};
由於單鏈表升序排列,可以參照前面的文章將有序數群組轉換為平衡二叉搜尋樹, 先求的鏈表中的結點的值儲存在數組中,然後採用相同的方法實現,時間複雜度為O(N)。當然也可以不額外採用數組儲存結點值,只是在每次遞迴的時候需要找出鏈表的中間元素,由於每次尋找中間元素需要O(N/2)的時間,一共需要O(lgN)尋找,所以總的時間為O(NlgN)。更好的解法我們可以採用自底向上的方法,在這裡我們不再需要每次尋找中間元素。下面代碼依舊需要鏈表長度作為參數,計算鏈表長度時間複雜度為O(N),而轉換演算法時間複雜度也為O(N),所以總的時間複雜度為O(N)。
BinaryTree* sortedListToBST(struct node*& list, int start, int end) { if (start > end) return NULL; // same as (start+end)/2, avoids overflow int mid = start + (end - start) / 2; BinaryTree *leftChild = sortedListToBST(list, start, mid-1); BinaryTree *parent = new BinaryTree(list->data); parent->left = leftChild; list = list->next; parent->right = sortedListToBST(list, mid+1, end); return parent;} BinaryTree* sortedListToBST(struct node *head, int n) { return sortedListToBST(head, 0, n-1);}代碼中需要注意的是每次調用sortedListToBST函數時,list位置都會變化,調用完函數後list總是指向mid+1的位置(如果滿足返回條件,則list位置不變)。例如如果鏈表只有2個節點3->5->NULL,則初始start=0,end=1。則mid=0,繼而遞迴調用sortedListToBST(list, start,mid-1),此時直接返回NULL。即左孩子為NULL, 根結點為3,而後鏈表list指向5,再調用sortedListToBST(list, mid+1, end),而這次調用返回結點5,將其賦給根結點3的右孩子。這次調用的mid=1,調用完成後list已經指向鏈表末尾。
英文地址Convert Sorted List to Balanced Binary Search Tree