270. 272 Closest Binary Search Tree Value

https://leetcode.com/problems/closest-binary-search-tree-value/description/

270. 272 Closest Binary Search Tree Value_第1张图片
image.png

这道题应该LOGN就好做,如果这个值比K大,记一下MIN DIFF。然后往小的走。反之亦然。一直走到树根,所有的路径里,最小的MIN DIFF就是解。
证明很简单,如果当前值已经比K大,你还往右边走,DIFF只会越来越大。那有没有可能先往右再往左走反而小呢。不可能。因为BST性质决定。所有右子树的节点都比根节点大。

double minDiff = 2.0*Integer.MAX_VALUE;
    int minPoint = -1;
    public int closestValue(TreeNode root, double target) {
        help(root,target);
        return minPoint;
    }
    private void help(TreeNode cur, double tar){
        if(cur == null) return;
        
        if(cur.val>tar){
            if((double)cur.val - tar < minDiff){
                minDiff = cur.val-tar;
                minPoint = cur.val;
            }
            help(cur.left,tar);
        }else{
            if(tar - (double)cur.val  < minDiff){
                minDiff = tar-cur.val;
                minPoint = cur.val;
            }
            help(cur.right,tar);
        }
    }

迭代写法:

public int closestValue(TreeNode root, double target) {
        TreeNode cur = root;
        double minDiff = 2.0*Integer.MAX_VALUE;
        int minPoint = -1;
        while(cur != null){
            if(Math.abs((double)cur.val-target) < minDiff){
                minDiff = Math.abs((double)cur.val-target);
                minPoint = cur.val;
            }
            if(cur.val

follow up :


270. 272 Closest Binary Search Tree Value_第2张图片
image.png

根据BST的性质,我们可以用中序遍历。一共需要K个,所以当结果集大于K个的时候,我们需要做比较。如果新进来的和TAR的差,小于队列头的(为什么是队列头?因为进结果集的是有顺序的,队列头是最远端,一定会差比后面队列的大。如果TAR比所有的节点都小,这个逻辑可以验证下来正确,因为后面进来的是不会小于队列头了)。就弹出队列头,插入这个。如果比队列头大了。就直接RETURN 了。

LinkedList res = new LinkedList<>();
    public List closestKValues(TreeNode root, double target, int k) {
        help(root,target,k);
        return res;
    }
    private void help(TreeNode cur, double tar, int k) {
        if(cur == null) return;
        help(cur.left,tar,k);
        if(res.size()==k){
            if(Math.abs(res.get(0)-tar)>Math.abs(cur.val-tar)){
                res.pollFirst();
                res.offerLast(cur.val);
            }else{
                return;
            }
        }else{
            res.offerLast(cur.val);
        }
        help(cur.right,tar,k);
    }

follow up:Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?

小于On 那应该就是LOG N 了。我们可以想一下,如果我们知道最接近TAR的2个点。一个是前驱,一个是后继。那么每次我们都选更近的一个放进结果集。同时我们可以用LOGN 的时间得到后继的后继,或者前驱的前驱。那么时间复杂度就是K*LOGN了。如果已知一个点在BST,要找后继,和前驱确实是LOGN的,基本功。这里就需要存PARENT了。所以我们想到用STACK这个数据结果。
那么怎么找最接近TAR的2个点,用LOGN呢?
我们可以用TAR》CUR往右走,同时把CUR放入前驱里tar。《cur往左走,同时把cur放入后继里。
因为你往左走了,如果还有机会比CUR大,那么这个大的幅度一定比之前那个后继要小。所以我们可以确保栈顶一定是最接近CUR的后继和前驱。那么就可以写代码了。

public List closestKValues(TreeNode root, double target, int k) {
        Stack pres = new Stack<>();
        Stack sucs = new Stack<>();
        TreeNode cur = root;
        while(cur != null){
            if(target < cur.val){
                sucs.push(cur);
                cur = cur.left;
            }else{
                pres.push(cur);
                cur = cur.right;
            }
        }
        List res = new ArrayList<>();
        while(k>0){
            double pre = pres.isEmpty()?Long.MIN_VALUE:pres.peek().val;
            double succ = sucs.isEmpty()?Long.MAX_VALUE:sucs.peek().val;
            if(Math.abs(pre-target) s){
        TreeNode pre = s.pop();
        TreeNode cur = pre.left;
        while(cur!=null){
            s.push(cur);
            cur = cur.right;
        }
    }
    private void getSuc(Stack s){
        TreeNode suc = s.pop();
        TreeNode cur = suc.right;
        while(cur!=null){
            s.push(cur);
            cur = cur.left;
        }
    }

你可能感兴趣的:(270. 272 Closest Binary Search Tree Value)