C++算法题 - 二叉搜索树

530. 二叉搜索树的最小绝对差

LeetCode_link


给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。

差值是一个正数,其数值等于两值之差的绝对值。

示例 1
在这里插入图片描述
输入:root = [4,2,6,1,3]
输出:1

示例 2
在这里插入图片描述
输入:root = [1,0,48,null,null,12,49]
输出:1

提示
树中节点的数目范围是 [2, 10^4]
0 <= Node.val <= 10^5


思路:用左子树和右子树的范围计算差值,很罗嗦,耗时长

/**
 * 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 {
public:
    int getMinimumDifference(TreeNode* root) {
        auto f = found(root);
        return f[0];
    }
    vector<int> found(TreeNode* root){
        int min_range, max_range;
        int sub = 100002;
        if(root->left == nullptr){
            min_range = root->val;
        }else{
            auto left_found = found(root->left);
            min_range = left_found[1];
            sub = min(sub, left_found[0]);
            sub = min(sub, (root->val - left_found[2]));
        }
        if(root->right == nullptr){
            max_range = root->val;
        }else{
            auto right_found = found(root->right);
            max_range = right_found[2];
            sub = min(sub, right_found[0]);
            sub = min(sub, (right_found[1] - root->val));
        }
        return {sub, min_range, max_range};
    }
};

思路:用中序遍历,记住中序遍历中前一个节点的数值

class Solution {
private:
    int pre = -1;
    int min_sub = 100002;
public:
    int getMinimumDifference(TreeNode* root) {
        if(root == nullptr) return min_sub;
        getMinimumDifference(root->left);
        if(pre == -1)   pre = root->val;
        else{
            min_sub = min(min_sub, root->val - pre);
            pre = root->val;
        }
        getMinimumDifference(root->right);
        return min_sub;
    }
};

230. 二叉搜索树中第K小的元素

LeetCode_link


给定一个二叉搜索树的根节点 root ,和一个整数 k ,请你设计一个算法查找其中第 k 个最小元素(从 1 开始计数)。

示例 1
在这里插入图片描述
输入:root = [3,1,4,null,2], k = 1
输出:1

示例 2
在这里插入图片描述
输入:root = [5,3,6,2,4,null,null,1], k = 3
输出:3

提示
树中的节点数为 n 。
1 <= k <= n <= 10^4
0 <= Node.val <= 10^4


思路

/**
 * 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 {
private:
    int count = 0;
public:
    int kthSmallest(TreeNode* root, int k) {
        if(root == nullptr) return -1;
        if(count > k) return -1;
        int left = kthSmallest(root->left, k);
        count ++;
        if(count == k)  return root->val;
        int right = kthSmallest(root->right, k);
        return max(left, right);
    }
};

98. 验证二叉搜索树

LeetCode_link


给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1
在这里插入图片描述
输入:root = [2,1,3]
输出:true

示例 2
在这里插入图片描述
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

提示
树中节点数目范围在 [1, 104]
-2^31 <= Node.val <= 2^31 - 1


思路:从底往上划范围,判断父节点符不符合要求

/**
 * 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 {
private:
    bool yes = true;
public:
    bool isValidBST(TreeNode* root) {
        valid(root);
        return yes;
    }
    pair<int, int> valid(TreeNode* root){
        if(yes == false)    return {};
        int min_l, max_l, min_r, max_r, min_a, max_a;
        if(root->left == nullptr){
            min_a = root->val;
        }else{
            auto le = valid(root->left);
            min_l = le.first;
            max_l = le.second;
            if(root->val <= max_l){
                yes = false;
                return {};
            }
            min_a = min_l;
        }
        if(root->right == nullptr){
            max_a = root->val;
        }else{
            auto ri = valid(root->right);
            min_r = ri.first;
            max_r = ri.second;
            if(root->val >= min_r){
                yes = false;
                return {};
            }
            max_a = max_r;
        }
        return {min_a, max_a};
    }

};

思路:从顶往下判断是否符合,注意数值范围,要用long

class Solution {
private:
    bool yes = true;
public:
    bool isValidBST(TreeNode* root) {
        return valid(root, LONG_MIN, LONG_MAX);
    }
    bool valid(TreeNode* root, long min_range, long max_range){
        if(root == nullptr) return true;
        if(root->val >= max_range || root->val <= min_range)    return false;
        return valid(root->left, min_range, root->val) && valid(root->right, root->val, max_range);
    }
};
  • 15
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
二叉排序树,也称为二叉搜索树,是一种数据结构,它是一棵二叉树,其中每个节点都包含一个键值,且左子树中的所有键值都小于该节点的键值,右子树中的所有键值都大于该节点的键值。通过这种方式,我们可以快速地对数据进行查找、插入和删除操作。 在排序问中,我们可以使用减治法来实现二叉排序树算法。具体来说,我们可以将排序问分解为两个子问:首先,将前半部分数据排序;然后,将后半部分数据排序。在排序过程中,我们可以利用二叉排序树的特性来建立一棵树,并将数据按照顺序插入到树中。当所有数据插入完毕后,我们可以通过遍历树来将数据按照升序输出。 下面是使用C++实现二叉排序树算法的示例代码: ```cpp #include <iostream> using namespace std; // 二叉排序树结构体 struct BSTNode { int data; // 数据 BSTNode* left; // 左子树指针 BSTNode* right; // 右子树指针 }; // 创建新节点 BSTNode* createNode(int data) { BSTNode* newNode = new BSTNode; newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } // 插入节点 BSTNode* insertNode(BSTNode* root, int data) { if (root == NULL) { return createNode(data); } if (data < root->data) { root->left = insertNode(root->left, data); } else { root->right = insertNode(root->right, data); } return root; } // 中序遍历输出 void inorderTraversal(BSTNode* root) { if (root != NULL) { inorderTraversal(root->left); cout << root->data << " "; inorderTraversal(root->right); } } // 测试函数 int main() { int arr[] = { 6, 3, 8, 2, 5, 7, 9 }; int n = sizeof(arr) / sizeof(arr[0]); BSTNode* root = NULL; for (int i = 0; i < n; i++) { root = insertNode(root, arr[i]); } inorderTraversal(root); return 0; } ``` 在上述代码中,我们首先定义了一个二叉排序树结构体,并实现了创建节点、插入节点、中序遍历输出等函数。接着,我们定义了一个测试函数,用于测试二叉排序树算法的正确性。在测试函数中,我们首先定义了一个数据数组,并计算出数据个数。然后,我们通过循环将每个数据插入到二叉排序树中。最后,我们调用中序遍历函数来输出排序后的数据。 通过实验对比分析,我们可以发现,使用减治法实现二叉排序树算法的时间复杂度为O(nlogn),空间复杂度为O(n),与其他排序算法相比,效率较高。但是,在某些情况下,由于二叉排序树的不平衡性,可能会导致算法效率下降,因此我们需要采取一些措施来保证二叉排序树的平衡性,例如AVL树、红黑树等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

x_fengmo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值