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

题目:

思路:

【1】拿到树或者链表的话其实少不了是要遍历的,而树的遍历存在三种:先序遍历(根左右),中序遍历(左根右),后序遍历(左右根)。而我们发现如果是数字的话其实中序遍历是最符合我们的要求的。如:

 

【2】基于中序遍历,将数据按顺序放入数组中。

【3】进行优化:1.首先题目求得是第几个,所以不一定要存入数组,其次,如果树很大,那边左边的遍历其实是无用的,所以可以考虑将顺序倒转,如左根右变为,右根左,形成数组的倒排。而且一旦遍历到了目标结果后立马中断遍历,不做额外的工作,减少消耗。

 

代码展示:

优化之后:

//时间0 ms击败100%
//内存41.4 MB击败49.49%
class Solution {
    int res, k;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return res;
    }
    void dfs(TreeNode root) {
        if(root == null) return;
        dfs(root.right);
        if(k == 0) return;
        if(--k == 0) res = root.val;
        dfs(root.left);
    }
}

 

基于中序遍历,将数据按顺序放入数组中:这种理论上时间和空间辅助度都为O(N),因为遍历了整棵树,调用栈也是这么多。

//时间1 ms击败32.21%
//内存42.1 MB击败9.68%
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int kthLargest(TreeNode root, int k) {
        List<Integer> list=new ArrayList<>();
        inOrder(root,list);
        int i=list.size()-k;
        return list.get(i);
    }
    public void inOrder(TreeNode root,List<Integer> list){
        if(root == null)
            return;
        inOrder(root.left,list);
        list.add(root.val);
        inOrder(root.right,list);
    }
}

 

posted @ 2023-02-17 15:37  忧愁的chafry  阅读(13)  评论(0编辑  收藏  举报