230.二叉搜索树中第K小的元素
标签: tree, binary-search-tree, depth-first-search
难度: Medium
通过率: 74.23%
原题链接: https://leetcode.com/problems/kth-smallest-element-in-a-bst/description/
题目描述
给定一个二叉搜索树的根节点和一个整数k,返回树中第k小的节点值(1索引数)。
解题思路
在二叉搜索树(BST)中,中序遍历将节点按升序排列。因为树的特性,左子树的所有节点值总是小于根节点,右子树的所有节点值大于根节点。通过对这棵树执行中序遍历,我们可以得到所有节点值的有序排列,然后选择第k个最小的值即可。具体步骤如下:
- 初始化一个空列表用于存储中序遍历的结果。
- 定义一个递归函数,用于对树进行中序遍历:
- 如果当前节点为 空,返回。
- 递归遍历左子树。
- 将当前节点值添加到结果列表中。
- 递归遍历右子树。
 
- 对根节点调用这个递归函数,得到中序遍历的结果列表。
- 返回结果列表中的第k-1个元素(因为列表是0索引,而k是1索引)。
代码实现
- Python
- C++
- JavaScript
- Java
# Python 代码实现
# 定义树节点
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
# 定义函数来找出BST中第k小的元素
def kthSmallest(root: TreeNode, k: int) -> int:
    # 中序遍历的结果
elements = []
    # 内部函数用于中序遍历
    def inorder(node):
        if node is None:
            return
        # 遍历左子树
        inorder(node.left)
        # 记录当前节点
        elements.append(node.val)
        # 遍历右子树
        inorder(node.right)
    # 执行中序遍历
    inorder(root)
    # 返回中序遍历结果中的第k-1个元素
    return elements[k-1]
// C++ 代码实现
// 定义树节点
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
    int kthSmallest(TreeNode* root, int k) {
        // 用于存储中序遍历结果的列表
        vector<int> elements;
        // 内部函数进行中序遍历
        inorder(root, elements);
        // 返回第k-1个最小的元素
        return elements[k-1];
    }
private:
    void inorder(TreeNode* node, vector<int>& elements) {
        if (node == nullptr) return;
        // 遍历左子树
        inorder(node->left, elements);
        // 存储当前节点的值
        elements.push_back(node->val);
        // 遍历右子树
        inorder(node->right, elements);
    }
};
// JavaScript 代码实现
// 定义树节点
function TreeNode(val, left, right) {
    this.val = (val===undefined ? 0 : val);
    this.left = (left===undefined ? null : left);
    this.right = (right===undefined ? null : right);
}
// 找出BST中第k小的元素
var kthSmallest = function(root, k) {
    // 结果数组来存储中序遍历结果
    const elements = [];
    // 定义中序遍历递归函数
    const inorder = function(node) {
        if (!node) return;
        // 访问左子树
        inorder(node.left);
        // 存储当前节点
        elements.push(node.val);
        // 访问右子树
        inorder(node.right);
    };
    // 执行中序遍历
    inorder(root);
    // 返回结果数组中的第k-1个元素
    return elements[k-1];
};
// Java 代码实现
// 定义树节点
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
class Solution {
    public int kthSmallest(TreeNode root, int k) {
        // 保存中序遍历结果的列表
        List<Integer> elements = new ArrayList<>();
        // 进行中序遍历
        inorder(root, elements);
        // 返回中序遍历结果中的第k-1个元素
        return elements.get(k - 1);
    }
    private void inorder(TreeNode node, List<Integer> elements) {
        if (node == null) return;
        // 遍历左子树
        inorder(node.left, elements);
        // 记录当前节点
        elements.add(node.val);
        // 遍历右子树
        inorder(node.right, elements);
    }
}
复杂度分析
时间复杂度:,因为在最坏情况下我们需要访问所有节点进行中序遍历。
空间复杂度:,因为中序遍历结果需要包含所有节点的值,额外的递归栈空间在最坏情况下达到树的高度,即。