LeetCode 230-Kth Smallest Element in a BST(BST,第k大元素)

LeetCode 230-Kth Smallest Element in a BST

题干:

给定一棵二叉搜索树,求它的第k大元素的值是多少。

解:

方法1:

利用中序遍历得到有序数组的特性。

int cnt = 0;
    int ans;
    int kthSmallest(TreeNode* root, int k) {
        traverse(root, k);
        return ans;
    }
    void traverse(TreeNode* root, int k){
        if(!root) return;
        traverse(root->left, k);
        ++cnt;
        if(cnt == k){
            ans = root->val;
            return;
        }
        else if(cnt > k) return;
        traverse(root->right, k);
    }

方法2(优化):

利用节点所在的子树大小,得到节点排名,从而判断第 k k k大元素在哪棵子树中(或为根节点)。

siz[x]数组记录以 x x x为根节点的子树的大小。在一棵子树中,根节点的排名取决于左子树的大小,所以若要寻找第 k k k大元素,需要将 k k k与左子树大小siz[x->left]作对比,若:

  • s i z ≥ k siz\ge k sizk,说明第 k k k大元素在左子树中,往左子树递归;
  • s i z = = k − 1 siz == k-1 siz==k1,说明根节点就是第 k k k大元素,返回根节点的值;
  • s i z < k − 1 siz < k - 1 siz<k1,说明第 k k k大元素在右子树中,往右子树递归

(注意,此题不能自己额外定义BST的size字段,在增删元素时也不能动态维护,所以在求siz时需要额外遍历整棵树,复杂度并未优化)

map<TreeNode*, int> siz;
    int kthSmallest(TreeNode* root, int k) {
        getSize(root);
        return queryKth(root, k);   
    }
    void getSize(TreeNode* root){
        if(!root){
            siz[root] = 0;
            return;
        } 
        getSize(root->left);
        getSize(root->right);
        siz[root] = siz[root->left] + siz[root->right] + 1;
    }
    int queryKth(TreeNode* root, int k){
        if(siz[root->left] >= k) return queryKth(root->left, k);
        else if(siz[root->left] < k - 1) return queryKth(root->right, k - siz[root->left] - 1);
        else return root->val;
    }

若初始时定义了size字段(或额外siz数组)+增删元素时能够动态维护size,那么该算法的时间复杂度为 O ( l o g n ) O(logn) O(logn)

struct TreeNode {
      int val;
      int size; // 记录以该节点为根节点的子树的大小
      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) {}
  };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值