zoukankan      html  css  js  c++  java
  • Closest Binary Search Tree Value II

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

    Note:

    • Given target value is a floating point.
    • You may assume k is always valid, that is: k ≤ total nodes.
    • You are guaranteed to have only one unique set of k values in the BST that are closest to the target.

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

    这是Closest Binary Search Tree Value的一道拓展题目。查找和target最接近的k个值。

    思路其实是对BST中最接近target的值的前继和后继做一个merge。合并出k个值即可。我的直接思路是先找到最近的这个节点,之后每次调用getPredecessor(N)和getSuccessor(N)的函数来获得当前处理到的结点的前继或者后继。找到最靠近的结点的复杂度为O(logn)(Closest Binary Search Tree Value),之后每次查找前继和后继的复杂度为O(logn)(Inorder Successor in BST)。所以总的复杂度为O(logn+ klogn) = O(klogn)。代码如下:

    class Solution(object):
        def closestKValues(self, root, target, k):
            """
            :type root: TreeNode
            :type target: float
            :type k: int
            :rtype: List[int]
            """
            #first find the closet value, then find the predecessor or successor of the node, merge k
            closet = root
            cur = root
            while cur:
                if abs(cur.val - target) < abs(target - closet.val):
                    closet = cur
                if cur.val > target:
                    cur = cur.left
                else:
                    cur = cur.right
            pre = self.getPredecessor(root, closet)
            succ = self.getSuccessor(root, closet)
            res = [closet.val]
            k -= 1
            while k and pre and succ:
                if abs(pre.val - target) < abs(succ.val - target):
                    res.append(pre.val)
                    pre = self.getPredecessor(root, pre)
                else:
                    res.append(succ.val)
                    succ = self.getSuccessor(root, succ)
                k -= 1
         
            if k > 0:
                if pre:
                    while k:
                        res.append(pre.val)
                        pre = self.getPredecessor(root, pre)
                        k -= 1
                else:
                    while k:
                        res.append(succ.val)
                        succ = self.getSuccessor(root, succ)
                        k -= 1
            return res
            
        def getPredecessor(self, root, p):
            pre = None
            while root:
                if root.val < p.val:
                    pre = root
                    root = root.right
                else:
                    root = root.left
            return pre
            
        def getSuccessor(self, root, p):
            succ = None
            while root:
                if root.val > p.val:
                    succ = root
                    root = root.left
                else:
                    root = root.right
            return succ

    但是这种解法显然不是最优的,每次查找前继和后继都是从树根开始的,中间每次重复走了很多路程。一个比较好的思路就是类似于Binary Search Tree Iterator,利用一个栈存储元素,每次pop元素时可以压入后继的序列。保存整个查找路径的值,节约了很多的时间。代码如下:

    # Definition for a binary tree node.
    # class TreeNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.left = None
    #         self.right = None
    
    class Solution(object):
        def closestKValues(self, root, target, k):
            """
            :type root: TreeNode
            :type target: float
            :type k: int
            :rtype: List[int]
            """
            res = []
            pred = []
            succ = []
            cur = root
            while cur:
                if cur.val > target:
                    succ.append(cur)
                    cur = cur.left
                else:
                    pred.append(cur)
                    cur = cur.right
                    
            while k:
                if not pred and not succ:
                    break
                elif not pred:
                    res.append(self.getSuccessor(succ))
                elif not succ:
                    res.append(self.getPredecessor(pred))
                elif abs(pred[-1].val - target) < abs(succ[-1].val - target):
                    res.append(self.getPredecessor(pred))
                else:
                    res.append(self.getSuccessor(succ))
                k -= 1
                    
            return res
                
        def getPredecessor(self, st):
            popped = st.pop()
            p = popped.left
            while p:
                st.append(p)
                p = p.right
            return popped.val
            
        def getSuccessor(self, st):
            popped = st.pop()
            p = popped.right
            while p:
                st.append(p)
                p = p.left
            return popped.val
            
            

    这种解法的时间和空间复杂度理论上都是O(klogn)。但是时间复杂度显然要优于我想出的第一个解法。

  • 相关阅读:
    死锁篇
    java线程池
    sql server 多行数据指定字符串拼接
    动态提交 表格
    ABP
    DDD学习
    sql 语句插入数据返回id
    Post方式提交,通过上下文HttpContext,Request[""]获取
    JQ的过滤隐藏
    sql 查询有多少行
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5668359.html
Copyright © 2011-2022 走看看