剑指offer-二叉搜索树的第K个节点
题目描述
给定一颗二叉搜索树,请找出按序排列的第K个的节点。
输入:
5 / \ 3 7 / \ / \ 2 4 6 8
输出:
若K=3,则输出4
解题思路
二叉搜索树性质可知,左子树所有节点均小于当前节点,右子树节点均大于当前节点。可以根据左子树数量确定第K个节点位置。
1、若左子树节点数为K,则第K个节点为左子树的最右节点。
2、若左子树节点数为K-1,则第K个节点为当前节点。
3、若左子树节点数大于K,则第K个加点在左子树中,递归求左子树第K个节点即可。
4、若左子树节点数小于K-1,假设为S,则第K个节点为右子树第K-S-1个节点, 递归求右子树第K-S-1个节点即可。
基于以上思路,代码实现如下:
//根据先序遍历求二叉树节点总数
int NodesOfTree(TreeNode *node) {
if (NULL == node) {
return 0;
}
int res = 1;
res += NodesOfTree(node->left);
res += NodesOfTree(node->right);
return res;
}
//求取二叉树最大子节点
TreeNode *GetMaxNodeOfTree(TreeNode *root) {
if (NULL == root) {
return NULL;
}
while (NULL != root->right) {
root = root->right;
}
return root;
}
//主程序
TreeNode* KthNode(TreeNode* pRoot, int k)
{
if (NULL == pRoot) {
return NULL;
}
int leftCounts = NodesOfTree(pRoot->left); //获取左子树节点数
if (leftCounts == k-1) { //若左子树节点数为K-1
return pRoot;
} else if (leftCounts == k) { //若左子树节点数为K
return GetMaxNodeOfTree(pRoot->left);
} else if (leftCounts > k) { //若左子树节点数大于K
return KthNode(pRoot->left, k);
} else { //若左子树节点数小于K-1
return KthNode(pRoot->right, k-leftCounts-1);
}
}
TreeNode定义如下:
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
========================================================
另附上大神思路:
由于二叉树中序遍历所得到的节点顺序即为大小排序,故可以按中序遍历方式求解。代码如下:
int count = 0; //全局变量记录当前遍历至第几个节点,**其实可以作为引用参数传递给函数
TreeNode *KthNode(TreeNode *pRoot, int k) {
if (NULL != pRoot) {
TreeNode *res = KthNode(pRoot->left, k);
if(NULL != res) {
return res;
}
if (++count == k) {
return pRoot;
}
return KthNode(pRoot->right, k);
}
return NULL;
}
大神代码就是精简,还需要继续学习。