题目描述
给定一棵结点数为n
二叉搜索树,请找出其中的第 k
小的TreeNode
结点值。
- 返回第
k
小的节点值即可 - 不能查找的情况,如二叉树为空,则返回
-1
,或者k
大于n
等等,也返回-1
- 保证
n
个节点的值不一样
数据范围:0 ≤ n ≤ 10000
,0 ≤ k ≤ 10000
,树上每个结点的值满足0 ≤ val ≤ 1000
。
如输入{5,3,7,2,4,6,8},3
时,二叉树{5,3,7,2,4,6,8}
如下图所示:
该二叉树所有节点按结点值升序排列后可得[2,3,4,5,6,7,8]
,所以第3
个结点的结点值为4
,故返回对应结点值为4的结点即可。
题目地址:https://www.nowcoder.com/practice/57aa0bab91884a10b5136ca2c087f8ff
解题思路
- 如果对于普通二叉树:
直接暴力法,遍历所有节点存入vector
。再排序后返回对应k - 1
下标的元素即可。
代码一:遍历
void DFS(TreeNode* root) {
if (!root) return;
DFS(root->left);
v.push_back(root->val);
DFS(root->right);
}
int KthNode(TreeNode* proot, int k) {
if (!proot || k <= 0) return -1;
DFS(proot);
if (k > v.size()) return -1;
return v[k - 1];
}
虽然暴力破解可以解决,利用空间缓存结果,但可见这种方法十分不优雅…而且空间复杂度也为O(N)
,所以需要对结果提前进行剪枝,不需要存储额外的空间。
- 题解为二叉搜索树:
根据BS-Tree
的性质,其中序遍历结果就是升序数组,免去排序一步,直接获取结果。
代码二:递归
int count = 0; //标记遍历的节点数,用来和k对比
int result = -1;
int KthNode (TreeNode* proot, int k) {
if(!proot || k <= 0) return -1;
KthNode(proot->left, k);
++count;
if(count == k)
return result = proot->val;
KthNode(proot->right, k);
return result;
}