LintCode-900: Closest Binary Search Tree Value

900 · Closest Binary Search Tree Value
Algorithms
Easy
Accepted Rate
54%

Description
Solution93
Notes
Discuss99+
Leaderboard
Record

Description
Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.

Given target value is a floating point.
You are guaranteed to have only one unique value in the BST that is closest to the target.
Example
Example1

Input: root = {5,4,9,2,#,8,10} and target = 6.124780
Output: 5
Explanation:
Binary tree {5,4,9,2,#,8,10}, denote the following structure:
5
/
4 9
/ /
2 8 10
Example2

Input: root = {3,2,4,1} and target = 4.142857
Output: 4
Explanation:
Binary tree {3,2,4,1}, denote the following structure:
3
/
2 4
/
1

我用的方法就是二分递归。当root->val > target时,结果只可能在root和左子树中选,否则就是在root和右子树中选。
注意!虽然pass了,但是还是有漏洞。关键在这一行
if (!root) return INT_MAX;
这里可能不对,因为如果某个节点为空,target是INT_MAX的话,INT_MAX就成了最佳结果了。
代码如下:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: the given BST
     * @param target: the given target
     * @return: the value in the BST that is closest to the target
    */
    int closestValue(TreeNode * root, double target) {
        if (!root) return INT_MAX; //注意!这里可能不对,因为如果某个节点为空,target是INT_MAX的话,INT_MAX就成了最佳结果了。
        double currGap=abs(root->val-target);

        if (target>root->val) {
            if (root->right) {
                int rightCandidate = closestValue(root->right, target);
                double rightGap=abs(rightCandidate - target);
                if (rightGap<currGap)
                    return rightCandidate;
            }
            return root->val;
    
        } else {
            if (root->left) {
                int leftCandidate = closestValue(root->left, target);
                double leftGap=abs(leftCandidate - target);
                if (leftGap<currGap)
                    return leftCandidate;
            }
            return root->val;
        }
    }
};

注意:下面的解法不对。因为当!root=0时,我们不能返回0。否则如果target是负数而二叉树的节点都是正数的话,这个0就是最佳结果了。但这是不对的,因为二叉树上没有0这个节点。所以下面的递归版上是根据kid是否为空来的,而不是根据root是否为空来的。

int closestValue(TreeNode *root, double target) {
        if (!root) return 0; //这里不对!看看case {2, #, 3} target=-3
        if (!root->left && !root->right) return root->val;
        double rootAbsDiff = abs(root->val - target);
        int closest = 0;
        if (target < root->val) {
            closest = closestValue(root->left, target);
        } else {
            closest = closestValue(root->right, target);
        }
        if (abs(closest - target) > abs(root->val - target)) {
            closest = root->val;
        }
        return closest;
    }
};

另外看到这个链接给出了简明扼要的递归和迭代两种解法,非常好。
http://rainykat.blogspot.com/2017/01/leetcode-270-closest-binary-search-tree.html
递归版:

public class Solution {
    public int closestValue(TreeNode root, double target) {
        // 选出子树的根节点
        TreeNode kid = target < root.val ? root.left : root.right;
        // 如果没有子树,也就是递归到底时,直接返回当前节点值
        if(kid == null) return root.val;  //注意!这一行很牛,包括了root节点没有子节点,和root节点的那个要递归的子节点为空的两种情况!
        // 找出子树中最近的那个节点
        int closest = closestValue(kid, target);
        // 返回根节点和子树最近节点中,更近的那个节点
        return Math.abs(root.val - target) < Math.abs(closest - target) ? root.val : closest;
    }
}

迭代版:
We the node is in tree so traveling the BST and keep a value closet to target

Complexity: O(lgN)

public class Solution {
    public int closestValue(TreeNode root, double target) {
        int closest = root.val;
        while(root!=null){
            //if current root.val is closer, update closest 
            closest = Math.abs(closest-target)<Math.abs(root.val-target)?closest:root.val;
            //do binary search
            root = target<root.val?root.left:root.right;
        }
        return closest;
    }
}

三刷: 前序遍历+二分。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: the given BST
     * @param target: the given target
     * @return: the value in the BST that is closest to the target
     */
    int closestValue(TreeNode *root, double target) {
        closest = root->val;
        helper(root, target);
        return closest;
    }
private:
    int closest = 0;
    void helper(TreeNode *root, double target) {
        if (!root) return;
        //if (!root->left && !root->right) { //注意:这里不能加这行,要不然左右节点只有一个的情况就没有处理。
            if (abs(root->val - target) < abs(closest - target)) closest = root->val;
        //    return;
        //}
        if (target < root->val) helper(root->left, target);
        else helper(root->right, target);
        return;
    }
};

解法3:中序遍历。这个时间复杂度是O(h+k)。h是树的高度,k是返回的点是中序遍历的第几个点。这个算法太慢。不优。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: the given BST
     * @param target: the given target
     * @return: the value in the BST that is closest to the target
     */
    int closestValue(TreeNode *root, double target) {
        stack<TreeNode *> stk;
        int res = root->val;
        while (root || !stk.empty()) {
            while (root) {
                stk.push(root);
                root = root->left;
            }
            root = stk.top();
            stk.pop();
            if (abs(root->val - target) < abs(res - target)) res = root->val;
            root = root->right;
        }
        return res;
    }
};

三刷
还是inorder traversal。注意光这么traversal的时间复杂度是O(n)。没有二分的好。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: the given BST
     * @param target: the given target
     * @return: the value in the BST that is closest to the target
     */
    int closestValue(TreeNode *root, double target) {
        closest = root->val;
        helper(root, target);
        return closest;
    }
private:
    int closest;
    void helper(TreeNode *root, double target) {
        if (!root) return;
        helper(root->left, target);
        if (abs(root->val - target) < abs(closest - target)) {
            closest = root->val;
        }
        helper(root->right, target);
    }
};

解法4:中序遍历+二分。
参考的labuladong的思路。这个方法很好!时间复杂度O(logn)。

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: the given BST
     * @param target: the given target
     * @return: the value in the BST that is closest to the target
     */
    int closestValue(TreeNode *root, double target) {
        closest = root->val;
        helper(root, target);
        return closest;
    }
private:
    int closest;
    void helper(TreeNode *root, double target) {
        if (!root) return;

        if (target < root->val) {
            helper(root->left, target);
            if (abs(root->val - target) < abs(closest - target)) {
                closest = root->val;
            }
        } else {
            if (abs(root->val - target) < abs(closest - target)) {
                closest = root->val;
            }
            helper(root->right, target);
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您的代码中给 `#Tips2` 元素添加了一个 `click` 事件监听器,在点击 `#Tips2` 元素时会显示一个 `layer.tips`。在 `layer.tips` 的 `success` 回调函数中添加了一个点击事件监听器,用于关闭所有的 `layer.tips`。但是,由于您在添加点击事件监听器时没有等待 `layer.tips` 加载完成,因此很可能会出现立即被关闭的情况。 为了避免这种情况,您可以在 `layer.tips` 的 `end` 回调函数中添加点击事件监听器,确保 `layer.tips` 加载完成后再添加监听器。具体实现方式如下: ```javascript // 给 #Tips2 元素添加一个点击事件监听器 $('#Tips2').on("click", function () { // 显示 layer.tips,并在显示完成后添加点击事件监听器 layer.tips('提示:如果展示的报表格式和导出的不同,需配置导出报表格式', '#Tips2', { tips: 3, success: function (layero) { // 在 end 回调函数中添加点击事件监听器 layero.end(function () { document.addEventListener('click', function (e) { // 判断点击的元素是否为 layer.tips 的目标元素或其子元素 if (!e.target.matches('.layui-layer-Tips') && !e.target.closest('.layui-layer-Tips')) { // 关闭所有的 layer.tips layer.closeAll('tips'); } }); }); } }); $(".layui-layer-tips .layui-layer-content").attr({'style': "opacity: 0.8;left: -47%;font-size: 14px !important;"}); $(".layui-layer-TipsG.layui-layer-TipsB").attr({'style': " right: 12px;left: auto;width: 0;top: -13px !important;left: 48% !important;height: 0;border-left: 7px solid transparent;border-right: 7px solid transparent;border-bottom: 7px solid black;transform: rotate(0deg) !important;"}); }); ``` 这段代码中,我们在 `layer.tips` 的 `success` 回调函数中添加了一个 `end` 回调函数,并在其中添加了点击事件监听器,用于关闭所有的 `layer.tips`。由于 `end` 回调函数会在 `layer.tips` 关闭后执行,因此可以确保 `layer.tips` 加载完成后再添加监听器。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值