LeetCode 108. 109. 将有序数组/链表转换为二叉搜索树

108. 将有序数组转换为二叉搜索树

难度:简单。
标签:二叉搜索树,数组,分治。

正确解法:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {

    TreeNode* get(vector<int> nums, int left, int right){
        if(left > right)return nullptr;
        else if(left == right){
            TreeNode* cur = new TreeNode(nums[left]);
            return cur;
        }
        int mid = (left + right + 1) / 2;
        TreeNode* cur = new TreeNode(nums[mid]);
        cur->left = get(nums, left, mid - 1);
        cur->right = get(nums, mid + 1, right);
        return cur;
    }

public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        return get(nums, 0, nums.size() - 1);
    }
};

结果:
在这里插入图片描述
怎么好慢,明明方法都差不多。

109. 有序链表转换二叉搜索树

难度:中等。
标签:二叉搜索树,链表,分治。

难点在于链表不像数组那样可以按索引访问,也不能直接获取其大小。
刚开始想到的是用快慢指针找其中间的点。

写这个解法,出现了很多小问题。
正确解法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {

    ListNode* getMiddle(ListNode* node, ListNode* endNode){
        ListNode* fast = node, *slow = node;
        while(fast != endNode && fast->next != endNode){
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }

    TreeNode* get(ListNode* beginNode, ListNode* endNode){
        if(beginNode == nullptr || beginNode == endNode)return nullptr;

        ListNode* mid = getMiddle(beginNode, endNode);
        TreeNode* cur = new TreeNode(mid->val);
        cur->left = get(beginNode, mid);
        cur->right = get(mid->next, endNode);
        return cur;
    }

public:
    TreeNode* sortedListToBST(ListNode* head) {
        return get(head, nullptr);
    }
};

结果:
在这里插入图片描述

官方题解的方法二更快。

链表本来就是平衡二叉树的中序遍历,将中序遍历结合起来使用,按链表的顺序来构建二叉树,这样不需要使用快慢指针找中间的node,开始计算链表长度,使用链表的索引来完成。

注意build函数第一个参数,要加取地址符,对单纯指针变量本身的修改无法作用到原指针变量,所以需要通过引用来实现修改指针变量。

正确解法:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {

    int getLength(ListNode* head){
        ListNode* node = head;
        int len = 0;
        while(node->next != nullptr){
            len++;
            node = node->next;
        }
        return len;
    }

    TreeNode* build(ListNode*& node, int left, int right){
        if(left > right)return nullptr;
        int mid = (left + right + 1) / 2;
        TreeNode* cur = new TreeNode();
        cur->left = build(node, left, mid - 1);
        cur->val = node->val;
        node = node->next;
        cur->right = build(node, mid + 1, right);
        return cur;
    }

public:
    TreeNode* sortedListToBST(ListNode* head) {
        if(head == nullptr)return nullptr;
        int len = getLength(head);
        return build(head, 0, len);
    }
};

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值