[Leetcode]Convert Sorted List to Binary Search Tree

Given a singly linked list where elements are sorted in ascending order, convert it to a height balanced BST.

第一思路就是先把鏈表元素取出來,存到數組裏,然後用把數組轉爲平衡BST的方法,結果內存溢出。看來這道題不允許O(n)的空間複雜度。

要用類似數組轉爲平衡BST的方法,就要不斷尋找中間元素。爲了減少空間複雜度,只能不斷遍歷鏈表,去尋找中間元素。這裏用快慢指針可以降低一些求中間元素的時間複雜度。

class Solution{
public:
	TreeNode *sortedListToBST(ListNode *head) {
		if (NULL == head) return NULL;
		return convert(head, NULL);
	}
	ListNode *searchMid(ListNode *left, ListNode *right){
		ListNode *slow = left, *fast = left;
		while (fast != right && fast->next != right){
			fast = fast->next->next;
			slow = slow->next;
		}
		return slow;
	}
	TreeNode *convert(ListNode *head, ListNode *end){
		if(NULL == head) return NULL;
		if (head->next == end || head == end){
			TreeNode *newNode = new TreeNode(head->val);
			return newNode;
		}
		ListNode *mid = searchMid(head, end);
		TreeNode *newNode = new TreeNode(mid->val);
		newNode->left = convert(head,mid);
		if(mid->next != end) newNode->right = convert(mid->next,end);
		return newNode;
	}
};

上邊的方法不多說了,比較容易寫出來。說實話這個方法中規中矩,時間複雜度比較高。一直想降低複雜度,但是沒有想到好方法。在網上看可很多,中遞歸的方法可以實現O(n)的時間複雜度。

利用中遞歸,自底向上的用中序構建這棵平衡BST。因爲要順序遍歷鏈表,因此遞歸中 的節點指針要不斷向後移動,所以要使用指針的引用,讓指針不斷變化。

class Solution{
public:
	TreeNode *sortedListToBST(ListNode *head){
		int len = calLen(head);
		return convert(head, 0, len - 1);
	}
	int calLen(ListNode *head){
		ListNode *tmp = head;
		int len = 0;
		while (tmp != NULL){
			tmp = tmp->next;
			len++;
		}
		return len;
	}
	TreeNode *convert(ListNode *&node, int left, int right){
		if (left > right) return NULL;
		int mid = (left + right) >> 1;
		TreeNode *leftN = convert(node, left, mid - 1);
		TreeNode *root = new TreeNode(node->val);
		root->left = leftN;
		node = node->next;
		root->right = convert(node, mid + 1, right);
		return root;
	}
};

其實這道題的關鍵在於把握BST的性質,中序遍歷BST,就是升序排列樹的元素。那倒過來,順序遍歷升序鏈表,其實就是按中序自底向上生成平衡BST。


再就是從Run Time來看,兩種方法其實差不了多少,都在100多ms。雖然leetcode的運行時間有時不準,但這也一定程度上暴露了遞歸的弊病----慢.......



發佈了35 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章