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

版权声明:转载请注明出处!谢谢! https://blog.csdn.net/qq_28114615/article/details/86559233

目录

1 题目描述

2 题目分析

3 代码实现

3.1 中序遍历方法

3.2 结点计数方法


1 题目描述

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 个最小的元素。

说明:
你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。

示例 1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 1

示例 2:

输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 3

2 题目分析

       一看到求第K小的问题,应该会容易想到建立大顶堆来做,但是如果这道题采用大顶堆的方式来做的话,是比较麻烦的,还得转换为数组,这样的话就完全忽视了二叉搜索树本身的特点。

       为了利用二叉搜索树的特点,一种可以采取的方法就是对二叉搜索树进行中序遍历,遍历结果必定是个升序数组,当数组长度达到k时,那么数组末尾的元素就是二叉搜索树的第K小元素了。不过这样的话就需要一个大小为O(K)的开辟辅助空间。

       为了既利用二叉搜索树的特点,又能减少辅助空间的开销,可以直接对左子树结点进行计数,如果左子树的结点数等于k-1的话,说明当前结点就是第k小的结点了;如果左子树结点数小于k-1的话,说明第k小的结点在当前结点的右边,假设左子树上的结点有num个,那么此时就递归查找右子树上第k-1-num小的元素;如果左子树结点大于k-1的话,说明第k小的结点就在左子树上,那么就递归查找左子树上第k小的元素。

3 代码实现

3.1 中序遍历方法

int kthSmallest(TreeNode* root, int k) {
        vector<int>nums;

        int count=0;   //用于计数

        midOrder(root,nums,k,count);
        
        
        return nums[k-1];
    }
void midOrder(TreeNode* root,vector<int>& nums,int k,int& count)
    {
        if(!root||count==k)return ;   //如果计数到k,则直接返回
        
        midOrder(root->left,nums,k,count);
        nums.push_back(root->val);
        count++;  //计数加一
        midOrder(root->right,nums,k,count);
        
        return ;
    }

3.2 结点计数方法

int kthSmallest(TreeNode* root, int k) {
        
        int num=count(root->left);  //计算左子树上结点数目
        
        if(num==k-1)return root->val;   //左子树上结点数目等于K-1,当前结点即是第k小结点
        if(num>k-1)return kthSmallest(root->left,k);  //左子树上结点数目大于K-1,说明第k小结点在左子树上
        
        
        return kthSmallest(root->right,k-1-num);//左子树上结点数目小于K-1,说明第k小结点在右子树上
}
int count(TreeNode* root)
{
        if(!root)return 0;
        return count(root->left)+count(root->right)+1;
}

猜你喜欢

转载自blog.csdn.net/qq_28114615/article/details/86559233
今日推荐