方法一:将链表转为数组来处理
解题思路:
因为链表不好处理,所以我先把链表处理成数组,因为是一个升序数组,所以直接将中间的数当成根结点,然后对左半部分的节点和右半部分的节点进行递归构建二叉搜索树。
在递归函数中,有两种情况需要考虑。第一种情况是传入的left值大于right值,说明是个null节点;第二种情况是传入的left==right,说明传入的区间只有一个节点,返回该节点即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
if(head == NULL) return NULL;
//先将链表转为数组
vector<int> nums;
while(head){
nums.push_back(head->val);
head = head->next;
}
return getBST(nums, 0, nums.size()-1);
}
TreeNode* getBST(vector<int>& nums, int l, int r){
if(l > r) return NULL;
if(l == r){
TreeNode* tmp = new TreeNode(nums[l]);
return tmp;
}
int mid = (l + r) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = getBST(nums, l, mid-1);
root->right = getBST(nums, mid+1, r);
return root;
}
};
方法二:直接对链表进行切割
解题思路:
因为链表是已经排好序的,可使用快慢指针来找到中间的节点,用last指针记录中间节点的前一个节点,然后通过将last的next置为null,将链表一分为二。
程序中需要注意的是,当函数输入的链表只有两个节点的时候,last和slow是指向同一节点的,需要做一个条件判断,然后再递归生成左右子树。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
if(head == NULL) return NULL;
ListNode* slow = head;
ListNode* fast = head;
ListNode* last = slow;
while(fast->next && fast->next->next){
last = slow;
slow = slow->next;
fast = fast->next->next;
}
fast = slow->next; //需要更新一下fast,不然将last->next置为null之后,slow->next可能也被置为null了(当slow和last指向同一个节点的时候)
last->next = NULL;
TreeNode* tmp = new TreeNode(slow->val);
if(slow != last) tmp->left = sortedListToBST(head);
tmp->right = sortedListToBST(fast);
return tmp;
}
};