Segment Tree

  • First, try to build the segment tree.

    • lintcode
    • suggest code: Currently recursion recommended. (For coding exercise, u can just start with "Interval minimum number" below.)
      """
      Definition of SegmentTreeNode:
      class SegmentTreeNode:
      def __init__(self, start, end):
      self.start, self.end = start, end
      self.left, self.right = None, None
      """ class Solution:
      """
      @param: start: start value.
      @param: end: end value.
      @return: The root of Segment Tree.
      """
      def build(self, start, end):
      # write your code here
      if start > end:
      return
      root = SegmentTreeNode(start, end)
      if start == end:
      return root
      mid = (end - start) / 2 + start
      root.left = self.build(start, mid)
      root.right = self.build(mid + 1, end)
      return root
    • Edge case:
      • Trees are building by pointers, so u must consider the null pointers!!!
      • if start > end
  • Try to know about segment tree.
    • wiki
    • Exactly as its name, segment tree is used to store segments.
    • A segment tree is a tree for storing intervals, or segments. It allows querying which of the stored segments contains a given pionts.
    • It is, in principle, a static structure; that is, it's a structure that cannot be modified once it's built.
    • Complexity:
      • A segment tree of a set I of n intervals uses O(nlogn) storage and can be built in O(nlogn) time.
      • Segements trees support searching for all the intervals that contain a query point in O(logn + k), k being the number of retrieved intervals or segments.
  • Try to use segment tree for simple query...
    • Recursion recommended too. But to careful to consider all the cases, see below:

      """
      Definition of SegmentTreeNode:
      class SegmentTreeNode:
      def __init__(self, start, end, max):
      self.start, self.end, self.max = start, end, max
      self.left, self.right = None, None
      """ class Solution:
      """
      @param: root: The root of segment tree.
      @param: start: start value.
      @param: end: end value.
      @return: The maximum number in the interval [start, end]
      """
      def query(self, root, start, end):
      # write your code here
      if start > end:
      return
      if (start <= root.start and end >= root.end):
      return root.max
      mid = (root.end - root.start) / 2 + root.start
      if end <= mid:
      return self.query(root.left, start, end)
      if start > mid:
      return self.query(root.right, start, end)
      return max(self.query(root.left, start, mid), self.query(root.right, mid + 1, end))
    • Then try to modify the tree...
      Please be familiar with this way of recursion: return current val for each recursion.
      """
      Definition of SegmentTreeNode:
      class SegmentTreeNode:
      def __init__(self, start, end, max):
      self.start, self.end, self.max = start, end, max
      self.left, self.right = None, None
      """ class Solution:
      """
      @param: root: The root of segment tree.
      @param: index: index.
      @param: value: value
      @return:
      """
      def modify(self, root, index, value):
      # write your code here
      if not root or index < root.start or index > root.end:
      return
      self.helper(root, index, value) def helper(self, root, index, value):
      if root.start == root.end:
      if root.start == index:
      root.max = value
      return root.max
      mid = (root.end - root.start) / 2 + root.start
      if index <= mid:
      val = self.helper(root.left, index, value)
      if root.right:
      val = max(val, root.right.max)
      root.max = val
      else:
      val = self.helper(root.right, index, value)
      if root.left:
      val = max(val, root.left.max)
      root.max = val
      return root.max
  • Now, try some usages.
    • Interval minimum number: lintcode

      • This is the most representative usage of segment: do interval aggregative operation.
      • """
        Definition of Interval.
        class Interval(object):
        def __init__(self, start, end):
        self.start = start
        self.end = end
        """
        class SegTreeNode:
        def __init__(self, start, end, val):
        self.start, self.end, self.val = start, end, val
        self.left, self.right = None, None class Solution:
        """
        @param: A: An integer array
        @param: queries: An query list
        @return: The result list
        """
        def intervalMinNumber(self, A, queries):
        # write your code here
        if not A or not queries:
        return []
        # 1. construct a segment tree
        root = self.construct_st(A, 0, len(A) - 1)
        # 2. search for each query
        res = []
        for query in queries:
        res.append(self.query_st(root, query.start, query.end))
        return res def construct_st(self, nums, start, end):
        if start == end:
        return SegTreeNode(start, end, nums[start])
        mid = (end - start) / 2 + start
        left = self.construct_st(nums, start, mid)
        right = self.construct_st(nums, mid + 1, end)
        root = SegTreeNode(start, end, min(left.val, right.val))
        root.left = left
        root.right = right
        return root def query_st(self, root, start, end):
        if start <= root.start and end >= root.end:
        return root.val
        root_mid = (root.end - root.start) / 2 + root.start
        if end <= root_mid:
        return self.query_st(root.left, start, end)
        if start > root_mid:
        return self.query_st(root.right, start, end)
        return min(self.query_st(root.left, start, root_mid), self.query_st(root.right, root_mid + 1, end))
    • For complicated implementation, try Interval Sum II.
  • Now, try some usage that not that obvious segment tree.
    • Count of Smaller Number.
      A useful thing to notice is that the value of from this array is value from 0 to 10000. So we can use a segment tree to denote [start, end, val] and val denotes how many numbers from the array is between [start, end].
    • class SegTreeNode:
      def __init__(self, start, end, val):
      self.start, self.end, self.val = start, end, val
      self.left, self.right = None, None class Solution:
      """
      @param: A: An integer array
      @param: queries: The query list
      @return: The number of element in the array that are smaller that the given integer
      """
      def countOfSmallerNumber(self, A, queries):
      # write your code here
      if not A:
      return [0 for i in range(len(queries))] # 1. construct a segment tree
      dict_A = {}
      for val in A:
      dict_A[val] = dict_A.get(val, 0) + 1
      root = self.con_st(0, 10000, dict_A)
      # 2. search
      res = []
      for query in queries:
      res.append(self.query_st(root, query))
      return res def con_st(self, start, end, dict_A):
      if start > end:
      return
      if start == end:
      return SegTreeNode(start, end, dict_A.get(start, 0))
      mid = (end - start) / 2 + start
      left = self.con_st(start, mid, dict_A)
      right = self.con_st(mid + 1, end, dict_A)
      root = SegTreeNode(start, end, left.val + right.val)
      root.left, root.right = left, right
      return root def query_st(self, root, query):
      if not root:
      return 0
      if query > root.end:
      return root.val
      if query <= root.start:
      return 0
      mid = (root.end - root.start) / 2 + root.start
      if query > mid:
      return root.left.val + self.query_st(root.right, query)
      if query <= mid:
      return self.query_st(root.left, query)
    • Then, try this: Count of smaller number before itself.
      • Obivously, we can use binary search to solve this just almost the same as 'Count of smaller number'. But for this problem, it will cost O(N^2) time, for the O(N) time for insert into a list.
      • But still, I tried binary search, as below:
        class Solution:
        """
        @param: A: an integer array
        @return: A list of integers includes the index of the first number and the index of the last number
        """ def countOfSmallerNumberII(self, A):
        # write your code here
        if not A:
        return []
        # binary search, O(NlogN) time(O(N^2) for insert takes O(N) each time), O(N) space
        sorted_subarr = []
        res = []
        for val in A:
        ind = self.binary_search(sorted_subarr, val)
        res.append(ind)
        return res def binary_search(self, sorted_subarr, val):
        if not sorted_subarr:
        sorted_subarr.append(val)
        return 0
        # 1. find the right-most number who is smaller than val
        left, right = 0, len(sorted_subarr) - 1
        while left < right - 1:
        mid = (right - left) / 2 + left
        if sorted_subarr[mid] < val:
        left = mid
        else:
        right = mid
        # 2. insert val into sorted_subarr
        if sorted_subarr[right] < val:
        sorted_subarr.insert(right + 1, val)
        return right + 1
        elif sorted_subarr[left] < val:
        sorted_subarr.insert(left + 1, val)
        return left + 1
        else:
        sorted_subarr.insert(left, val)
        return left
      • And a better choice is using segment tree. For each val in A, we search segment tree then insert it into tree.
        class SegTreeNode:
        def __init__(self, start, end, val):
        self.val, self.start, self.end = val, start, end
        self.left, self.right = None, None class Solution:
        """
        @param: A: an integer array
        @return: A list of integers includes the index of the first number and the index of the last number
        """ def countOfSmallerNumberII(self, A):
        # write your code here
        if not A:
        return []
        # 1. build segment tree, using O(10000log10000)
        root = self.build_st(0, max(A))
        # 2. search for target value then update segment tree
        res = []
        for val in A:
        res.append(self.search_st(root, val))
        self.update_st(root, val)
        return res def build_st(self, start, end):
        root = SegTreeNode(start, end, 0)
        if start == end:
        return root
        mid = (end - start) / 2 + start
        root.left = self.build_st(start, mid)
        root.right = self.build_st(mid + 1, end)
        return root def search_st(self, root, val):
        if val > root.end:
        return root.val
        if val <= root.start:
        return 0
        mid = (root.end - root.start) / 2 + root.start
        if val <= mid:
        return self.search_st(root.left, val)
        return root.left.val + self.search_st(root.right, val) def update_st(self, root, val):
        root.val += 1
        if root.start == root.end:
        return
        mid = (root.end - root.start) / 2 + root.start
        if val <= mid:
        self.update_st(root.left, val)
        else:
        self.update_st(root.right, val)

Summary of segment tree

  • 线段树的每个节点表示一个区间,子节点分别表示父节点的左右半区间。
  • 线段树的构建、查询和更新都可以使用递归。构建是O(NlogN) time, 查询和更新时O(logN) time,其中n是root的end - start。
  • 常见应用:求区间的最大最小值、区间的sum等。

Binary Search Tree

  • The definition of bst is very easy: x.left < x, x.right > x
  • Range search in bst: Search Range in BST.
    BST(tree)惯用套路:recursion
    class Solution:
    """
    @param: root: param root: The root of the binary search tree
    @param: k1: An integer
    @param: k2: An integer
    @return: return: Return all keys that k1<=key<=k2 in ascending order
    """
    def searchRange(self, root, k1, k2):
    # write your code here
    if not root or k1 > k2:
    return []
    results = []
    self.helper(root, k1, k2, results)
    return results def helper(self, root, start, end, results):
    if not root or start > end:
    return
    if root.val < start:
    self.helper(root.right, start, end, results)
    elif root.val > end:
    self.helper(root.left, start, end, results)
    else:
    self.helper(root.left, start, root.val, results)
    results.append(root.val)
    self.helper(root.right, root.val, end, results)

[Data Structure] Tree - relative的更多相关文章

  1. Python: tree data structure

    # 树结构 from pythonds.basic.stack import Stack #pip install pythonds from pythonds.trees.binaryTree im ...

  2. [Algorithms] Tree Data Structure in JavaScript

    In a tree, nodes have a single parent node and may have many children nodes. They never have more th ...

  3. 字典树(查找树) leetcode 208. Implement Trie (Prefix Tree) 、211. Add and Search Word - Data structure design

    字典树(查找树) 26个分支作用:检测字符串是否在这个字典里面插入.查找 字典树与哈希表的对比:时间复杂度:以字符来看:O(N).O(N) 以字符串来看:O(1).O(1)空间复杂度:字典树远远小于哈 ...

  4. LeetCode208 Implement Trie (Prefix Tree). LeetCode211 Add and Search Word - Data structure design

    字典树(Trie树相关) 208. Implement Trie (Prefix Tree) Implement a trie with insert, search, and startsWith  ...

  5. [LeetCode] Add and Search Word - Data structure design 添加和查找单词-数据结构设计

    Design a data structure that supports the following two operations: void addWord(word) bool search(w ...

  6. Finger Trees: A Simple General-purpose Data Structure

    http://staff.city.ac.uk/~ross/papers/FingerTree.html Summary We present 2-3 finger trees, a function ...

  7. Java for LeetCode 211 Add and Search Word - Data structure design

    Design a data structure that supports the following two operations: void addWord(word)bool search(wo ...

  8. LeetCode 笔记27 Two Sum III - Data structure design

    Design and implement a TwoSum class. It should support the following operations: add and find. add - ...

  9. hdu 4217 Data Structure? 树状数组求第K小

    Data Structure? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

随机推荐

  1. 怎样才能提交一个让开发人员拍手叫好的bug单

    怎样才能提交一个让开发人员拍手叫好的bug单 软件测试人员写得最多的文档就是测试用例和BUG,现在测试用例和BUG都没有标准的模板,每个公司使用的缺陷管理工具都有可能不一样,如果你换了一家公司就有可能 ...

  2. spring bean的初始化以及销毁

    spring bean初始化或销毁时执行某些方法,有很多使用场景.比如初始化时,启动bean中的线程池.销毁时释放资源,个人比较喜欢实现InitializingBean和 DisposableBean ...

  3. nginx--service配置

    nginx从今天开始进行相关学习了,包括:1.注册centos的service服务:2.相关的tomcat负载:3.https配置:4.session共享配置 1.注册centos的service服务 ...

  4. java之导入excel

    接口: /** * * Description: 导入excel表 * @param map * @param request * @param session * @return * @author ...

  5. PHP保留两位小数并且四舍五入及不四舍五入的方法

    php保留两位小数并且四舍五入 $num = 123213.666666; echo sprintf("%.2f", $num); php保留两位小数并且不四舍五入 $num = ...

  6. Html lable 标签

    Html lable 标签 <html> <body> <!-- label 关联光标标签,点击文字使得关联的标签获取光标.for="username" ...

  7. Python 堡垒机介绍

    堡垒机说明 由于运维行业流动性很高,也为了防止有人在服务中残留后门,照成安全隐患,在这里我们使用堡垒机保证服务器管理安全. 我们知道运维人员在登陆服务时需要登陆用户,从客户端到服务端的过程中堡垒机,将 ...

  8. 剑指offer(21)栈的压入、弹出序列

    题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序 ...

  9. 【python游戏编程04--加载位图与常用的数学函数】

    一.pygame中常用的数学函数 首先介绍两个角度和弧度转换的函数 math.degress()和math.radians()用法很简单,只要将数值传进去然后接受返回值就可以 math.cos(ang ...

  10. Bootstrap3基础 text-uppercase/lowercase/capitalize 字母大写、小写和首字母大写

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...