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的节点,然后进行查找。

相关推荐
geovindu12 分钟前
java: Gale-Shapley Algorithm
java·开发语言·后端·算法
冻柠檬飞冰走茶31 分钟前
PTA基础编程题目集 7-34 通讯录的录入与显示(C语言实现)
c语言·开发语言·数据结构·算法
zander25836 分钟前
LeetCode 79. 单词搜索
算法·深度优先
老洋葱Mr_Onion1 小时前
【C++】高精度模板
开发语言·c++·算法
脚踏实地皮皮晨1 小时前
003003002_WPF Grid 基类官方类定义逐行深度解析
开发语言·windows·算法·c#·wpf·visual studio
aaaameliaaa9 小时前
字符函数和字符串函数
c语言·笔记·算法
城管不管10 小时前
ReAct、Plan-and-Execute、Reflection 三大智能 Agent 范式核心区别
java·人工智能·算法·spring·ai·动态规划
月疯11 小时前
二分法算法(水平等分图形面积)
算法
豆瓣鸡11 小时前
算法日记 - Day3
java·开发语言·算法
白白白小纯11 小时前
算法篇—反转链表
c语言·数据结构·算法·leetcode