LeetCode:230二叉搜索树中第K小的元素

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    //用于计数和k作比较
    int count = 0;
    //用于返回最终的结果
    int result = -1;

    public int kthSmallest(TreeNode root, int k) {
        inorder(root,k);
        return result;
    }

    public void inorder(TreeNode node, int k){
        if(node == null || count >= k){
            return;
        }

        inorder(node.left,k);
        //计数加1
        count++;
        if(count == k){
            result = node.val;
            return;
        }
        inorder(node.right,k);
    }
}

因为左边的是最小的,我们要找的是从小到大的第k小的元素,所以只有在读取完左边的最小元素后才加1

处理逻辑:

前序遍历:一见到节点就报数,通常用于从上往下的路径搜索

中序遍历:二叉搜索树,从小到大唯一正确的报数时机

后序遍历:通常用于计算高度、深度和销毁树

进阶做法

java 复制代码
//带有 size 属性
class MyTreeNode {
    int val;
    int size; 
    MyTreeNode left;
    MyTreeNode right;
    public MyTreeNode(int val) {
        this.val = val;
        this.size = 1;
    }
}
class Solution {
    // 接收官方的普通树,进行转换
    public int kthSmallest(TreeNode root, int k) {
        // 官方的普通树,转换成带 size 树
        MyTreeNode myRoot = buildTree(root);
        
        return findKth(myRoot, k);
    }

    // TreeNode 转换成 MyTreeNode,并计算 size
    private MyTreeNode buildTree(TreeNode node) {
        if (node == null) return null;
        MyTreeNode myNode = new MyTreeNode(node.val);
        myNode.left = buildTree(node.left);
        myNode.right = buildTree(node.right);
        int leftSize = (myNode.left != null) ? myNode.left.size : 0;
        int rightSize = (myNode.right != null) ? myNode.right.size : 0;
        myNode.size = leftSize + rightSize + 1;
        return myNode;
    }

    //利用 size 找节点
    private int findKth(MyTreeNode curr, int k) {
    
        while (curr != null) {
            // 看看左部分有多少节点
            int leftSize = (curr.left != null) ? curr.left.size : 0;
            
            if (k <= leftSize) {
                // 目标一定在左边
                curr = curr.left;
            } else if (k == leftSize + 1) {
                // 左边刚好排满,当前节点就是我们要找的
                return curr.val;
            } else {
                // 目标在右边,减去当前节点左部分和当前节点的总数,拿着新 k 去右边找
                curr = curr.right;
                k = k - (leftSize + 1);
            }
        }
        return -1;
    }
}

重新定义节点结构,加入size;将原节点转换成带有size的节点,然后进行查找。

相关推荐
kisshyshy6 小时前
🍦 雪糕、食堂、火车厢:三幅漫画吃透栈、队列与链表
javascript·算法
猿人谷14 小时前
不只是 CPU 阈值:STAR 如何用 GAT + Transformer 做容器级自动扩缩容?
人工智能·算法
复杂网络15 小时前
Stable Diffusion 视觉大模型微调技术深度调研
算法
复杂网络15 小时前
基于 Stable Diffusion 架构的视觉大模型代表性工作与原理深度解析
算法
MrZhao40015 小时前
Agent Loop 如何用 Hook 扩展:权限、日志与工具拦截
算法
MrZhao40015 小时前
Agent 为什么需要 Skills:别把所有知识都塞进 system prompt
算法
JieE2122 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
JieE2123 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack203 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树3 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色