剑指offer-二叉搜索树的第K个节点

剑指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;
}

大神代码就是精简,还需要继续学习。

你可能感兴趣的:(算法)