Closest Binary Search Tree Value II

要点:通过iterator,把closest值附近的k个closest找到,从而time降为O(klgn)

  • in order iterator的本质:栈存当前见到,未来还要再访问到的node。当前见到是沿着left访问,而未来再见到就是到了right branch
  • 这题的iterator实现和一般的in-order iterator略有不同:inorder访问后的结点并不出栈而是直接继续push right subtree,当右子pop的时候,继续通过判断是否为右子决定是否pop父节点。如果是左子,那么父节点。而一般的iterator实现不需要连续验证父节点,因为在push right subtree之前已经出栈了。
  • 这题之所以不pop父节点是因为初始化(小就向左大就向右)后的stack状态和以当前点iterator的stack state是一样的,而向右走是不pop的。
  • 初始化和I的区别:最后只保留closest之前的在栈里,但是在完整路径走完之前是不知道的。所以只能最后截取。

https://repl.it/Cg9u/2 (scott solution)

https://repl.it/CiYU/2 (my)

错误点

  • cur1和cur2有可能过界,因为是超过一边的比较,但不会2个都过界。所以条件是not cur2 OR (cur1 and dist(cur1)<dist(cur2)
def closestKValues(self, root, target, k):

    # Helper, takes a path and makes it the path to the next node
def nextpath(path, kid1, kid2):
if path:
if kid2(path):
path += kid2(path), # 当前node(右子)进栈
while kid1(path):
path += kid1(path),
else:
kid = path.pop()
while path and kid is kid2(path):
kid = path.pop() # These customize nextpath as forward or backward iterator
kidleft = lambda path: path[-1].left
kidright = lambda path: path[-1].right # Build path to closest node
path = []
while root:
path += root,
root = root.left if target < root.val else root.right
dist = lambda node: abs(node.val - target)
path = path[:path.index(min(path, key=dist))+1] # Get the path to the next larger node
path2 = path[:]
nextpath(path2, kidleft, kidright) # Collect the closest k values by moving the two paths outwards
vals = []
for _ in range(k):
if not path2 or path and dist(path[-1]) < dist(path2[-1]):
vals += path[-1].val, # 当所有左子都访问后,如果当前点是父节点的右子,其为栈顶,在这里访问,之后如果其没右子,就被pop掉。和一般的iterator算法有什么不同?这里左子树访问完了的结点是不出栈的直接push右节点,当右子树访问完了... next: 右子访问结束呢? 所以要连续pop右子,这样可以保证不会再进到右子。而左子只会把自己pop掉,露出父结点
nextpath(path, kidright, kidleft)
else:
vals += path2[-1].val,
nextpath(path2, kidleft, kidright)
return vals
# 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)? # Hint: # Consider implement these two helper functions:
# getPredecessor(N), which returns the next smaller node to N.
# getSuccessor(N), which returns the next larger node to N.
# Try to assume that each node has a parent pointer, it makes the problem much easier.
# Without parent pointer we just need to keep track of the path from the root to the current node using a stack.
# You would need two stacks to track the path in finding predecessor and successor node separately.
# Hide Company Tags Google
# Hide Tags Tree Stack
# Hide Similar Problems (M) Binary Tree Inorder Traversal (E) Closest Binary Search Tree Value # 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]
"""
def next(stk, left, right):
top = stk[-1]
if right(top):
l = right(top)
while l:
stk.append(l)
l=left(l)
return stk[-1]
else:
top = stk.pop()
while stk and right(stk[-1])==top:
top = stk.pop()
return stk[-1] if stk else None # error: doesnt matter, will never be empty left = lambda x: x.left
right = lambda x: x.right stk = []
while root:
stk.append(root)
if root.val<target:
root = root.right
else:
root = root.left
# print [s.val for s in stk] dist = lambda x: abs(x.val-target)
stk1 = stk[:stk.index(min(stk, key=dist))+1] # error 1: how to get min and keep the index
stk2 = list(stk1) cur1 = stk1[-1]
cur2 = next(stk2, left, right)
res = [] for _ in xrange(k):
if not cur2 or (cur1 and dist(cur1)<dist(cur2)): # error
res.append(cur1.val)
cur1 = next(stk1, right, left)
else:
res.append(cur2.val)
cur2 = next(stk2, left, right) return res

边工作边刷题:70天一遍leetcode: day 82-1的更多相关文章

  1. 边工作边刷题:70天一遍leetcode: day 82

    Closest Binary Search Tree Value 要点: https://repl.it/CfhL/1 # Definition for a binary tree node. # c ...

  2. 边工作边刷题:70天一遍leetcode: day 89

    Word Break I/II 现在看都是小case题了,一遍过了.注意这题不是np complete,dp解的time complexity可以是O(n^2) or O(nm) (取决于inner ...

  3. 边工作边刷题:70天一遍leetcode: day 77

    Paint House I/II 要点:这题要区分房子编号i和颜色编号k:目标是某个颜色,所以min的list是上一个房子编号中所有其他颜色+当前颜色的cost https://repl.it/Chw ...

  4. 边工作边刷题:70天一遍leetcode: day 78

    Graph Valid Tree 要点:本身题不难,关键是这题涉及几道关联题目,要清楚之间的差别和关联才能解类似题:isTree就比isCycle多了检查连通性,所以这一系列题从结构上分以下三部分 g ...

  5. 边工作边刷题:70天一遍leetcode: day 85-3

    Zigzag Iterator 要点: 实际不是zigzag而是纵向访问 这题可以扩展到k个list,也可以扩展到只给iterator而不给list.结构上没什么区别,iterator的hasNext ...

  6. 边工作边刷题:70天一遍leetcode: day 101

    dp/recursion的方式和是不是game无关,和game本身的规则有关:flip game不累加值,只需要一个boolean就可以.coin in a line II是从一个方向上选取,所以1d ...

  7. 边工作边刷题:70天一遍leetcode: day 1

    (今日完成:Two Sum, Add Two Numbers, Longest Substring Without Repeating Characters, Median of Two Sorted ...

  8. 边工作边刷题:70天一遍leetcode: day 70

    Design Phone Directory 要点:坑爹的一题,扩展的话类似LRU,但是本题的accept解直接一个set搞定 https://repl.it/Cu0j # Design a Phon ...

  9. 边工作边刷题:70天一遍leetcode: day 71-3

    Two Sum I/II/III 要点:都是简单题,III就要注意如果value-num==num的情况,所以要count,并且count>1 https://repl.it/CrZG 错误点: ...

  10. 边工作边刷题:70天一遍leetcode: day 71-2

    One Edit Distance 要点:有两种解法要考虑:已知长度和未知长度(比如只给个iterator) 已知长度:最好不要用if/else在最外面分情况,而是loop在外,用err记录misma ...

随机推荐

  1. Java、Hibernate(JPA)注解大全

    1.@Entity(name=”EntityName”) 必须,name为可选,对应数据库中一的个表 2.@Table(name=””,catalog=””,schema=””) 可选,通常和@Ent ...

  2. 如何高效部署前端代码,如css,js...

    看了网上一些文章,做了点总结,顺便再加点自己的东西,简单的说下. 1.利用浏览器的304缓存,但是304叫协商缓存,还是需要与服务器通信一次 2.强制使用浏览器使用本地缓存(cache-control ...

  3. Treap树的基础知识

    原文 其它较好的的介绍:堆排序  AVL树 树堆,在数据结构中也称Treap(事实上在国内OI界常称为Traep,与之同理的还有"Tarjan神犇发明的"Spaly),是指有一个随 ...

  4. [小北De编程手记] : Lesson 01 - Selenium For C# 之 环境搭建

    在我看来一个自动化测试平台的构建,是一种很好的了解开发语言,单元测试框架,自动化测试驱动,设计模式等等等的途径.因此,在下选择了自动化测试的这个话题来和大家分享一下本人关于软件开发和自动化测试的认识. ...

  5. ServiceStack.Text反序列化lowercase_underscore_names格式的JSON

    代码: [Test] public void Test() { JsConfig.PropertyConvention = JsonPropertyConvention.Lenient; var js ...

  6. 硅谷新闻8--TabLayout替换ViewPagerIndicator

    1.关联库 compile 'com.android.support:design:23.3.0' 2.布局写上TabLayout <android.support.design.widget. ...

  7. 捋一捋Javascript数据类型转换规则

    一.数据类型 5种基本数据类型:Null/Undefined/String/Boolean/Number 1种复杂数据类型:Object 二.数据类型检测 传送门<几种JS数据类型方式及其局限性 ...

  8. Office版本差别引发的语法问题

    由于没有源代码,今天反编译了一个基于.NET的dll类库,再次遇到office版本差异问题,所以把它记录下来. 在反编译时,需要Aspose.Cells 5.3.1(Aspose是一套.NET类库,其 ...

  9. SharePoint 2013 自定义模板页后在列表里修改不了视图

    前言 最近系统从2010升级至2013,有自定义模板页.突然发现在列表中切换不了视图,让我很费解. 我尝试过以下解决方案: 去掉自定义css 去掉自定义js 禁用所有自定义功能 结果都没有效还是一样的 ...

  10. Sizing and Capacity Planning for SharePoint 2013 - Resources

    http://blogs.msdn.com/b/sanjaynarang/archive/2013/04/06/sizing-and-capacity-planning-for-sharepoint- ...