剑指 offer 54.二叉搜索树的第k个节点

54.二叉搜索树的第k个节点

题目

给定一棵结点数为n 二叉搜索树,请找出其中的第 k 小的TreeNode结点值。
1.返回第k小的节点值即可
2.不能查找的情况,如二叉树为空,则返回-1,或者k大于n等等,也返回-1
3.保证n个节点的值不一样

示例:

输入:
{5,3,7,2,4,6,8},3

返回值:
4

题目示例中的二叉搜索树的形状:

image.png

第 3 小的节点很明显是 4, 所以需要返回 4 。

思路

很明显,如果你熟悉二叉树的层序遍历的话,这题又可以秒了。只需要将二叉树进行层序遍历,然后将得到的二维数组打平排序即可得到结果。(注意:此时我们甚至都没有用到题目中说的二叉搜索树这个条件,只是当成了普通二叉树)

方法一:层序遍历

/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 *
 * @param proot TreeNode类
 * @param k int整型
 * @return int整型
 */
function KthNode(proot, k) {
    if(proot === null || k < 1) return -1
    // write code here
    const levelOrder = (root) => {
        let stack = [];
        let res = [];

        if (root === null) return res;

        stack.push(root);

        while (stack.length) {
            let size = stack.length;

            let arr = [];

            for (let i = 0; i < size; i++) {
                let node = stack.shift();
                arr.push(node.val);
                node.left && stack.push(node.left);
                node.right && stack.push(node.right);
            }

            res.push(arr);
        }

        return res;
    };
    // 得到层序遍历的结果
    let res = levelOrder(proot)
    // 将层序遍历得到的二维数组拍平并排序
    res = res.flat().sort((a,b)=>a-b)
    if(k > res.length) return -1
    return res[k-1]
}
module.exports = {
    KthNode: KthNode,
};

但是实际上这题并没有那么复杂,因为我们只是需要将每一个节点放入一个数组,然后排序即可得到结果。所以使用递归会更方便。

为什么使用层序遍历的方式来写,其实就是为了熟悉这个方法,虽然有点啰嗦了。

其实可以使用递归来写:

/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param proot TreeNode类 
 * @param k int整型 
 * @return int整型
 */
function KthNode( proot ,  k ) {
    // write code here
    let res = []
    function traversal(root) {
        if(root === null) return
        res.push(root.val)
        traversal(root.left)
        traversal(root.right)
    }
    traversal(proot)
    res.sort((a,b)=>a-b)
    if(k > res.length || res.length === 0 || k < 1) return -1
    return res[k-1]
}
module.exports = {
    KthNode : KthNode
};

方法二:二叉搜索树

题目中特地强调了这棵树是 二叉搜索树,那么二叉搜索树有什么特点呢?

下图中就是二叉搜索树的定义:

image.png

所以一棵树如果是二叉搜索树,这课树是有很明显的特点的。

根据二叉搜索树的左节点小于右节点的规律,其实我们不难推测出一个结论:二叉搜索树的中序遍历是递增的

根据这个特点,我们其实只需要中序遍历这个二叉搜索树,就可以得到我们想要的递增的数组了。

/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param proot TreeNode类 
 * @param k int整型 
 * @return int整型
 */
function KthNode( proot ,  k ) {
    // write code here
    const res = []
    const dfs = function (root) {
        if(root === null) return
        dfs(root.left)
        res.push(root.val)
        dfs(root.right)
    }
    dfs(proot)
    if(res.length === 0 || k > res.length || k < 1) return -1
    return res[k - 1]


}
module.exports = {
    KthNode : KthNode
};
  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

城南顾北

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值