二叉搜索树的第k大节点(二叉树的中序遍历)Leetcode 刷题日记 2021.2.25

Leetcode 刷题日记

2021.2.25

题目链接:

https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/

问题描述:

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

解答:

中序遍历的非递归实现

代码:

class Solution {
    public int kthLargest(TreeNode root, int k) {
        LinkedList<TreeNode> stack = new LinkedList<>();
        int index = 0;

        while(!stack.isEmpty() || root != null){
            while(root != null){
                stack.push(root);
                root = root.right;
            }
            root = stack.pop();
            if(++index == k) return root.val;
            root = root.left;
        }
        
        return -1;
    }
}

分析:

时间复杂度:O(n)
空间复杂度:O(n)

运行结果:

在这里插入图片描述

评注:

1.在查阅了许多相关资料之后,笔者认为对于树的非递归中序遍历,这种实现方法是较好的。在许多参考资料(如Weiss的《数据结构与算法分析 java语言描述》)中,中序遍历是通过记录节点的被访问次数实现的。笔者认为这种实现方式虽然更容易理解,但也使代码更加冗长,并且不能最大程度地体现栈的意义,不是一种具有较高普适性的方法。

2.对于非递归实现,中序遍历比先序遍历更加困难。其中一大难点就在于,在遍历完左子树后,如何顺利访问根节点并越过它访问右子树。下面笔者将针对这一问题对代码进行分析。需要注意的是,由于本题要求的是找出第k大节点,所以与“左-中-右”相反,代码实现的是“右-中-左”,但基本原理完全一致。

①第7至9行代码表示,只要一个节点不为空,就将其推入栈中,并把引用指向其右孩子,而这等效于,始终把节点的右孩子推入栈中。这个内层while循环结束后,root指针将停留在以起始节点(起始节点就是开始内层while循环之前的root节点)为根节点的子树上最大的节点处。

②第10至12行代码表示,如果右子树完成遍历,就应该把root指向其根节点。完成对根节点的遍历后再遍历左子树。

③最后谈一谈外层while的判断条件。只要栈不为空或者root指针不为空,则继续循环。这两个条件缺一不可。对于第一个条件,不必多说,如果栈内还有元素,说明尚未完成遍历,当然不能终止循环。但是第二个条件怎么理解呢?实际上可以考虑这样一个情形:完成对右子树的遍历之后,第10行代码将把根节点弹出,然后第12行会把root指向根节点的左孩子。此时栈中没有元素,但是左子树尚未完成遍历,可能存在两种情况:如果左孩子为空,说明左子树为空,可以终止循环;但是如果左孩子不为空,则说明左子树上有节点,当然不能终止循环。root != null的判断就是为了处理这种情况。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值