题目描述
方法一(中序历遍思想)
使用树的中序历遍,对于二叉搜索树,树的中序历遍得到的就是按照从小到大排序的一个序列。这里做了适当的改进,历遍的时候不再将数值保存到一个数组中,这样就不需要占用内存。直接通过记录当前历遍到第 i 个值(即第 i 大的数),和要求的 K 比较,相等就将其赋给保存结果的变量。但是这样做,程序仍然有优化的空间。因为,这个递归程序在得到了正确答案之后,并没有停下来,仍然在继续执行,直到完成整棵树的中序历遍才会终止。这里就不再使用奇技淫巧跳出递归。
/**
* 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:
int kthSmallest(TreeNode* root, int k) {
int num=0;
int res=0;
fun(root, k, num,res);
return res;
}
void fun(TreeNode* root, int k, int &num, int &res)
{
if(!root) return;
fun(root->left,k,num,res);
++num;
if(num == k)
{
res = root->val;
}
fun(root->right,k,num,res);
}
};
方法二(二分法思想)
通过计算左子树的节点个数来判断。如果左子树的节点个数为 k-1 ,那么说明根节点就是我们要找的数。如果左子树的节点数很多(>k-1),说明要找的节点在左子树,递归调用。如果左子树节点较少,说明要找的节点在右子树中。左子树加上根节点,一共有left_node+1个节点。那么在右子树中,只需要找第 小的数。
/**
* 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:
int kthSmallest(TreeNode* root, int k) {
int left_node = calculate(root->left);
if(left_node == k-1) return root->val;
if(left_node >k-1) return kthSmallest(root->left, k);
if(left_node <k-1) return kthSmallest(root->right,k-left_node-1);
}
int calculate(TreeNode* root)
{
if(!root) return 0;
int node_sum=0;
node_sum = 1 + calculate(root->left) + calculate(root->right);
return node_sum;
}
};
参考:https://blog.csdn.net/suibianshen2012/article/details/52051272