二叉搜索树第大K节点,剑指offer,力扣

目录

题目地址:

题目:

我们直接看题解吧:

解题方法:

难度分析:

审题目+事例+提示:

解题分析:

解题思路:

代码实现:

代码补充:

代码实现(非递归) :


题目地址:

LCR 174. 寻找二叉搜索树中的目标节点 - 力扣(LeetCode)

难度:简单

今天刷寻找二叉搜索树第大K节点,大家有兴趣可以点上看看题目要求,试着做一下。

题目:

剑指 Offer 54. 二叉搜索树的第k大节点

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

我们直接看题解吧:

快速理解解题思路小建议:

可以先简单看一下解题思路,然后照着代码看思路,会更容易理解一些。

解题方法:

利用递归+中序遍历方法

审题目+事例+提示:

1、题目中序列是以二叉搜索树方式存储

2、补充:

      二叉搜索树(BST,Binary Search Tree),也称二叉排序树或二叉查找树。

      二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:

  1. 非空左子树的所有键值小于其根结点的键值。
  2. 非空右子树的所有键值大于其根结点的键值。
  3. 左、右子树都是二叉搜索树。

解题分析:

二叉搜索树的中序遍历为 递增序列 ,

根据此性质,易得二叉搜索树的中序遍历 倒序 为 递减序列 。

因此,求 “二叉搜索树第 cnt大的节点” 可转化为求 “此树的中序遍历倒序的第 cnt个节点”。

中序遍历 为 “、根、” 顺序,递归法代码如下:

// 打印中序遍历
void dfs(TreeNode root) {
    if(root == null) return;
    dfs(root.left); // 左
    System.out.println(root.val); // 根
    dfs(root.right); // 右
}

中序遍历的倒序 为 “、根、” 顺序,递归法代码如下:

// 打印中序遍历倒序
void dfs(TreeNode root) {
    if(root == null) return;
    dfs(root.right); // 右
    System.out.println(root.val); // 根
    dfs(root.left); // 左
}

参考题解:LCR 174. 寻找二叉搜索树中的目标节点 - 力扣(LeetCode)

解题思路:

核心思路:简单讲,就是用临时变量count保存cnt, 进行递归操作,由于按照中序遍历倒叙,即节点值大小依次递减,每递归一次count就-1, 直到最后当count=0时,即遍历到第cnt大的节点。

首先定义两个全局变量:

    1、 res :用于存储目标的节点值

   2、count:作为临时变量,存储数值cnt(由于cnt不能跟着递归变化,因此用count代替)

最后返回res即可

递归部分:( 递归函数dfs传入根节点即可)

      a. 终止条件: 根节点判空操作,若root==null 则直接返回;
      b. 递归右子树: 即 dfs(root.right);

      c.if 条件判断(count==0)即找到目标节点,无需遍历,直接返回

      d. if 条件判断: (--count==0)

             `统计序号: 执行 cnt=cnt−1 (即从 cnt 减至 0 );
             `提前返回: 若 count=0,即当前节点为第cnt大节点,记录res值,直接返回;
      f. 递归左子树: 即 dfs(root.left) ;

 

代码实现:

class Solution {
    int res, count;//因此为了记录迭代进程和结果,引入类变量count和res

    public int findTargetNode(TreeNode root, int cnt) {

        count = cnt;//将形参值cnt对类变量count进行初始化
        dfs(root);//这里不需要引入形参cnt,dfs中直接使用的是初始值为cnt的类变量count
        return res;
    }

    void dfs(TreeNode root) {
        if(root == null) return;//当root为空,终止递归

        dfs(root.right);//遍历右子树

        if(count == 0) return;//当count=0 即找到目标res,终止递归

        if(--count==0){//先--,再判断
            res = root.val;//即当前节点为第cnt大节点,记录res
            return;//这里的return直接终止递归,无需dfs(root.left);
        }

        dfs(root.left);//遍历左子树
    }
}

代码补充:

1、题目指出:1 ≤ cnt ≤ N(二叉搜索树节点个数)

   因此无需考虑 cnt>Nc 的情况。
   若考虑,可以在中序遍历完成后判断 cnt>0 是否成立,若成立则说明 cnt>N 。

2、count==0的判断条件是否可以并到第一个if(root==null)中?

         注意,count==0得放在--count之前才有效,因为回溯的过程可能会继续--,这样会导致count<0,从而没有起到剪枝效果。

3、递归函数第一部分的判空操作的作用(二叉树递归必定写的部分,无脑写就完事了)

    a.根节点判空条件,即如果根节点为null则返回,
    b.作为递归的终止条件,即访问到叶子结点的下一个的时候为null,则返回

代码实现(非递归) :

二叉树的非递归一般都是通过 栈+循环的方法来实现

思路跟上面的大同小异,不同其中一点是这里的count时从增加到=cnt

class Solution { 
    public int findTargetNode(TreeNode root, int cnt) {
          // reverse-inorder (逆向中序排序 找到需要的第cut个就好了)
        LinkedList<TreeNode> stack = new LinkedList<>();
        TreeNode node = root;
        int count = 0;
        while(node != null || !stack.isEmpty()){
            if (node != null){
                stack.push(node);
                node = node.right;
            }else{
                // 说明是空了向左边走
                TreeNode pop = stack.pop();
                count++;
                if(count == cnt){//找到目标节点值
                    return pop.val;
                }
                node = pop.left;
            }
        }
        // 这里其实是没有必要的 但是必须要返回值
        return -1;
    }
}

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值