leetcode
leetcode 251 ~ 300
最接近的二叉搜索树值 II

最接近的二叉搜索树值 II

难度:

标签:

题目描述

代码结果

运行时间: 22 ms, 内存: 18.1 MB


/*
 * 思路:
 * 1. 使用中序遍历将二叉搜索树的节点值按升序存入一个列表。
 * 2. 使用Java Stream API对列表进行排序并找到距离目标值最近的k个值。
 */
import java.util.*;
import java.util.stream.Collectors;
 
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
 
public class Solution {
    public List<Integer> closestKValues(TreeNode root, double target, int k) {
        List<Integer> sortedValues = new ArrayList<>();
        inorderTraversal(root, sortedValues);
        return sortedValues.stream()
                           .sorted((a, b) -> Double.compare(Math.abs(a - target), Math.abs(b - target)))
                           .limit(k)
                           .collect(Collectors.toList());
    }
 
    private void inorderTraversal(TreeNode root, List<Integer> sortedValues) {
        if (root == null) return;
        inorderTraversal(root.left, sortedValues);
        sortedValues.add(root.val);
        inorderTraversal(root.right, sortedValues);
    }
}
 

解释

方法:

这个题解的思路是先通过中序遍历将二叉搜索树转换成一个有序数组,然后利用二分查找找到最接近目标值的位置。接着用双指针从该位置向两边扩展,每次选择与目标值差距更小的那个点加入答案,直至选出 k 个最接近的值。

时间复杂度:

O(n + k)

空间复杂度:

O(n + k)

代码细节讲解

🦆
为什么选择中序遍历来将二叉搜索树转换成有序数组?中序遍历与其他遍历方法(如前序或后序)相比有何优势?
在二叉搜索树(BST)中,中序遍历的过程会按照从小到大的顺序访问所有节点,这是因为对于任何一个节点,中序遍历先访问其左子树,然后是节点本身,最后是右子树。这样的访问顺序恰好符合二叉搜索树的有序性质。相比之下,前序和后序遍历则无法保证输出一个有序数组,因为它们访问节点的顺序与节点的大小顺序不一致。例如,前序遍历首先访问根节点,然后是左子树和右子树,这不会直接产生有序数组。因此,中序遍历是转换BST为有序数组的最自然和直接的方法。
🦆
二分查找找到的位置为何用`bisect_left`而不是`bisect_right`?这样选择对结果有什么潜在影响?
`bisect_left`函数在数组中找到第一个不小于目标值的元素的位置,而`bisect_right`则找到第一个大于目标值的元素的位置。使用`bisect_left`意味着如果目标值正好等于数组中的某个元素,那么返回的位置将是这些相等元素的最左侧位置。这种选择有助于在后续双指针过程中更平均地考虑目标值两侧的元素,避免偏向任一侧。如果使用`bisect_right`,则在相等元素较多的情况下可能跳过最接近的一侧,从而可能影响结果的最优性。
🦆
在双指针扩展过程中,当`left`或`right`指针越界时,程序如何保证仍然能选出足够的k个最接近的值?
在双指针过程中,如果一个指针(`left`或`right`)越界,程序会继续移动另一个仍在数组范围内的指针,直到收集到足够的k个元素。例如,如果`left`指针越界(小于0),则只增加`right`指针,反之亦然。由于数组已经包含了所有树节点的值,这种方法保证了即使一个方向的指针越界,仍然可以从另一方向获取足够的元素来满足k的需求。
🦆
如果目标值target非常接近某个节点值,但不完全等于任何节点值,二分查找和双指针策略在这种情况下是否还能有效工作?
是的,二分查找和双指针策略仍然有效。二分查找通过`bisect_left`找到最接近目标值的起始位置,即便这个位置的元素值不完全等于目标值。之后,双指针策略从这个位置开始向两边扩展,比较左右元素与目标值的差距,逐步选择最接近的元素。这种方法确保了即使目标值不等于任何节点值,也能找到最接近的k个值。

相关问题

二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

 

示例 1:

输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

输入:root = []
输出:[]

示例 3:

输入:root = [1]
输出:[1]

 

提示:

  • 树中节点数目在范围 [0, 100]
  • -100 <= Node.val <= 100

 

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

最接近的二叉搜索树值

最接近的二叉搜索树值