Problem Description: For a given sequence, the elements of any interval (i, j) are modified; modify any element for fast update
Tree-like array
The main feature of a tree-like array is the creation of a tree with a height of logn. The height of each layer is k, and the binary expression of the sequence element index distributed in this layer has a common feature, that is, the minimum two power is k.
There is a strong association between subtrees, that is, given a sequence of element index I, it is possible to infer the parent node of the node C[i] c[p],p=i+2^k, where K=i & (i ^ (i-1)) and the root node p=i-2^k of the previous subtree of the subtree where the element is located.
The relationship between the subtrees can be conveniently used to find the first n elements and all subtrees can be found; for the sake of updating, it is only necessary to logn the C[i] value and update the sequence elements.
# Leetcode 307# Tree Array # The nature of the tree array is still a binary tree, thus reaching O (logn) algorithm complexity # The most interesting thing about a tree array is that the lowest level is 0, the height of item I of the sequence is k,k represents the number of bits from the right 0 in the binary of I, that is, the minimum of 2 powers # From the binary point of view, it is very quick to conclude that 2^k = i & (i ^ (i-1)) # Gives a node I, which can quickly find its parent node (i + 2^k) and the root node of the most recent subtrees tree before it (i-2^k) # problem form: # 1. Given a fixed sequence, the quest for all items before N and: equals the sum of the root node values of all subtrees (# 2). Arbitrary modification of an element to a fixed sequence for fast update: equivalent to updating the value of the root node of all subtrees containing the node # The most tangled place or the root node array c, did not expect to be through the update request. Class Numarray (object): Def __init__ (self, Nums): "" ": Type Nums:list[int]" "" Self.nums = [0 for _ in nums] SELF.N = Len (nums) SELF.C = [0 for _ in Nums] for I, NUM in enumerate (nums): Self.update (i, NUM) def lowbit (self, x): # return X & (-X) return x & (x ^ (x-1)) def Update (self, I, Val): "" ": Type I:int:type val:int:rtype:void" "" Differen CE = val-self.nums[i] self.nums[i] = val while I < self.n:self.c[i] + = Difference i + = Self.lowbit (i + 1) def getsum (self, N): sum = 0 while n >= 0:sum + self.c[n] n-= self.lowbit (n + 1) return sum def Sumrange (self, I, j): "" ": Type I:int:type j:int:rtype:int" "" Return to Self . Getsum (j)-Self.getsum (i) + self.nums[i] # Your Numarray object would be instantiated and called as such: # obj = Numarray (nums) # obj.update (i,val) # param_2 = Obj.sumrange (i,j) nums = [1, 3, 5]x = Numarray (nums) # X . Update (0, 1) print (X.sumrange (0, 2)) # Print (x.getsum (0))
Segment Tree
A segment tree is a full-binary tree, that is, 0 or 2 of the degree of each node.
The main feature of the line segment tree is the constant split interval [s, e] for [s, mid] and [mid + 1, E], where mid = s + int ((E-S)/2). A node with a scale of 0 is a leaf, which contains only one number and is no longer equally divided.
the structure of line-segment tree is constructed by constructing nodes, and it is known that if the given sequence length is n, the number of leaf nodes is n, and the non-leaf nodes are N-1, that is, altogether 2n-1 node. the index of the defined root node is 0, its left subtree has a node of 1, and the right subtree has a node of 2. Generally speaking, if the current node is I, then its left node is (2 * i + 1), the right node is (2 * i + 2), so when the number of nodes is constructed, the index length is not N-1. (I do not know how much, there is a blog is 2 * 2 ^ (ceil (Logn)))-1, but the amount of data on a large leetcode is dead or alive . Similarly, a line tree can be used for summing and updating. Very ingenious! The operation of the segment tree is basically based on the recursive function, first give a total interval (that is, the root node corresponding to the interval), and then continue to split evenly, ask Getsbsumuntil (SS, Mid, Qs, QE, (2 * si) + 1) +
Getsbsumuntil (mid + 1, SE, QS, QE, (2 * si) + 2)
In addition, the segment tree can also be used for interval and maximum and interval substitution, next time.
# leetcode 307# segment Tree import MathClass Numarray (object): Def __init__ (self, Nums): "" ": Type Nums:list[int] "" "self.nums = nums SELF.N = Len (nums) self.st = [0 for _ in range (2 * 2 ^ int (math.log2 (sel F.N))] Self.constructstuntil (0, self.n-1, 0) def getmid (self, S, e): Return int (s + (E-S)/2) de F Constructstuntil (self, SS, SE, si): if ss = = Se:self.st[si] = Self.nums[ss] return self.st [Si] mid = self.getmid (ss, SE) self.st[si] = Self.constructstuntil (ss, Mid, (2 * si) + 1) + Self.constructstuntil (mid + 1, SE, (2 * si) + 2) return SELF.ST[SI] def updatauntil (self, SS, SE, I, SI, D Ifference): If I < SS or I > Se:return self.st[si] + = Difference if ss! = SE: MID = Self.getmid (ss, SE) Self.updatauntil (SS, Mid, I, (2 * si + 1), difference) Self.updataun Til (mid + 1, SE, I, (2 * Si + 2), difference) def update (self, I, Val): "" ": Type I:int:type val:int:rtype:voi D "" "difference = val-self.nums[i] self.nums[i] = Val self.updatauntil (0, self.n-1, I, 0, difference) def getsbsumuntil (self, SS, SE, QS, QE, si): if qs = = Qe:return Self.nums[qs] If (QS <= SS) and (QE >= SE): return self.st[si] if (qs > SE) or (QE < SS): return 0 mid = Self.getmid (ss, SE) return self.getsbsumuntil (SS, Mid, Qs, QE, (2 * si) + 1) + SELF.G Etsbsumuntil (mid + 1, SE, QS, QE, (2 * si) + 2) def sumrange (self, I, j): "" ": Type I:int:type J : Int:rtype:int "" "Return Self.getsbsumuntil (0, Self.n-1, I, J, 0) # Your Numarray Object would be instantiated and called as such: # obj = Numarray (nums) # obj.update (i,val) # param_2 = obj. Sumrange (i,j) nums = [-1]X = Numarray (nums) x.update (0, 1) print (x.sumrange (0, 0))
Tree-like array/segment tree