剑指Offer:[第15天 搜索与回溯算法(中等)]--->二叉搜索树的第k大节点

本文介绍了如何在二叉搜索树中寻找第k大的节点。利用二叉搜索树中序遍历的特性,将中序遍历顺序反转,通过递归遍历并计数,可以有效地找到第k大的节点。文章详细分析了思路,并提供了整体的C语言实现代码,同时讨论了时间复杂度和空间复杂度。
摘要由CSDN通过智能技术生成


一、题目描述

给定一棵二叉搜索树,请找出其中第 k 大的节点的值。

示例1:

输入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
输出: 4

示例2:

输入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
输出: 4

限制:

1 ≤ k ≤ 二叉搜索树元素个数


二、思路分析

注:思路分析中的一些内容和图片参考自力扣各位前辈的题解,感谢他们的无私奉献

思路

由于二叉搜索树的中序遍历为递增序列,可以知道二叉搜索树的中序遍历倒序为递减序列。因此,求二叉搜索树第k大的节点可转化为求此树的中序遍历倒序的第k个节点。
在这里插入图片描述
二叉搜索树的中序遍历步骤为:
----递归遍历左子树
----打印根结点
----递归遍历右子树
由上我们可以得出,二叉搜索树的中序遍历的倒叙步骤为:
----递归遍历右子树
----打印根结点
----递归遍历左子树
为求第k个节点,需要实现以下三项工作:
----递归遍历时计数,统计当前节点的序号
----递归到第k个节点时,应记录结果res
----记录结果后,后续的遍历即失去意义,应提前终止(即返回)
递归解析:
终止条件:当节点root为空(越过叶节点),则直接返回
递归右子树:即dfs(root.right)
三项工作
----提前返回: 若k=0,代表已找到目标节点,无需继续遍历,因此直接返回
----统计序号: 执行k=k-1(即从k 减至0)
----记录结果: 若k=0,代表当前节点为第k大的节点,因此记录res=root.val
递归左子树: 即dfs(root.left)
案例分析:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
复杂度分析:
时间复杂度 O ( N ) \rm{O(N)} O(N):当树退化为链表时(全部为右子节点),无论k的值大小,递归深度都为N,占用O(N)时间
空间复杂度 O ( N ) \rm{O(N)} O(N):当树退化为链表时(全部为右子节点),系统使用O(N)大小的栈空间


三、整体代码

整体代码如下

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

void dfs(struct TreeNode* root, int *k, int* res){
    if(root == NULL) return;   //节点为空,代表穿过叶节点了,直接return
    dfs(root->right, k, res);  //右子树中序遍历
    if(*k == 0) return;        //如果k为0了,代表已经找到了,直接返回即可
    if(--*k == 0) {            //如果k--为0,代表当前节点就是第k大的,然后保存当前节点值
        *res = root->val;
    }
    dfs(root->left, k, res);   //左子树中序遍历

}

int kthLargest(struct TreeNode* root, int k){
    int k_tmp = k; //定义两个变量,每次递归穿地址,这样才能修改这些变量的值
    int res = 0;
    dfs(root, &k, &res); //从根结点开始进行dfs
    return res;
}

运行,测试通过
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知初与修一

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

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

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

打赏作者

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

抵扣说明:

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

余额充值