272. Closest Binary Search Tree Value II

博客介绍了在BST中查找k个最接近元素的三种方法。方法1是中序遍历加排序,时间复杂度nlogn,空间复杂度n;方法2是中序遍历加堆,时间复杂度nlogk,空间复杂度n + k,也有不用堆的巧妙方法;方法3是快速选择,时间复杂度n,空间复杂度n。

在这里插入图片描述
方法1: inorder traversal + sort(override)。时间复杂nlogn,空间复杂n。

class Solution {
    public void inorder(TreeNode root, List<Integer> nums) {
        if (root == null) return;
        inorder(root.left, nums);
        nums.add(root.val);
        inorder(root.right, nums);
    }

    public List<Integer> closestKValues(TreeNode root, double target, int k) {
        List<Integer> nums = new ArrayList();
        inorder(root, nums);
        
        Collections.sort(nums, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Math.abs(o1 - target) < Math.abs(o2 - target) ? -1 : 1;
            }
        });
        return nums.subList(0, k);
    }
}

方法2: inorder traversal + heap. 这个heap将会 keep less close element first的规则,heap规定大小为k。所以我们遍历bst。每当heap满的时候我们需要判断是不是要把当前node加进heap(拿当前node大小与heap第一个元素大小比较,heap第一个元素就是与target差距最大的元素)。时间复杂nlogk。空间复杂n+k。

class Solution {
    public void inorder(TreeNode r, List<Integer> nums, Queue<Integer> heap, int k) {
        if (r == null) 
            return;
                    
        inorder(r.left, nums, heap, k);
        heap.add(r.val);
        if (heap.size() > k) 
            heap.remove();
        inorder(r.right, nums, heap, k);
    }

    public List<Integer> closestKValues(TreeNode root, double target, int k) {
        List<Integer> nums = new ArrayList();
        
        // init heap 'less close element first'
        Queue<Integer> heap = new PriorityQueue<>((o1, o2) -> Math.abs(o1 - target) > Math.abs(o2 - target) ? -1 : 1);
        inorder(root, nums, heap, k);
        return new ArrayList<>(heap);
    }
}

这个方法二也可以不用heap,但是这个方法非常的巧妙,要自己画图才知道为啥行得通,但是一般情况下都是要用heap的,因为要找到那个与target差距最大的元素。下面这个算法时间复杂n,空间复杂h。

public class Solution {
    public List<Integer> closestKValues(TreeNode root, double target, int k) {
        LinkedList<Integer> res = new LinkedList<>();
        collect(root, target, k, res);
        return res;
    }

    public void collect(TreeNode root, double target, int k, LinkedList<Integer> res) {
        if (root == null) return;
        collect(root.left, target, k, res);

        if (res.size() == k) {
            //if size k, add curent and remove head if it's optimal, otherwise return
            if (Math.abs(target - root.val) < Math.abs(target - res.peekFirst())) 
                res.removeFirst();
            else return;
        }
        res.add(root.val);
        collect(root.right, target, k, res);
    }
}

方法3: quick select。这个算法普遍应用于find kth closest/smallest/largest elemnt in。。。但是这个算法我今天没咋看懂。复盘的时候记得看一下。时间复杂n,空间复杂n。具体思路请参考lc官方解答3.

总结:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值