目录

三个月算法进阶--day81

节点的度

子树的数量

线段树

范围查询,对数时间,二叉树

叶节点包含原始数据,非叶节点包含数组的一个子范围上的聚合信息

构建线段树(区域和)

自下而上

def buildTree(nums):
    if nums:
        self.n = len(nums)
        self.tree = [0 for _ in range(self.n * 2)]
        for i in range(self.n, self.n * 2):
            self.tree[i] = nums[i - self.n]
        for i in range(self.n - 1, 0, -1):
            self.tree[i] = self.tree[i * 2] + self.tree[i * 2 + 1] 

更新线段树

def update(pos, val):
    pos += self.n
    self.tree[pos] = val
    while pos:
        left, right = pos, pos
        if pos % 2:
            left = pos - 1
        else:
            right = pos + 1
        self.tree[pos // 2] = self.tree[left] + self.tree[right]
        pos //= 2

区域和检索

def sumRange(l, r):
    l += self.n
    r += self.n
    sum = 0
    while l <= r:
        if l % 2:
            sum += self.tree[l]
            l += 1
        if not r % 2:
            sum += self.tree[r]
            r -= 1
        l //= 2
        r //= 2
    return sum

记录

leetcode第307题区域和检索-数组可修改

class NumArray:

    def __init__(self, nums: List[int]):
        self.n = len(nums)
        self.tree = [0 for _ in range(self.n * 2)]
        for i in range(self.n, self.n * 2):
            self.tree[i] = nums[i - self.n]
        for i in range(self.n - 1, 0, -1):
            self.tree[i] = self.tree[i * 2] + self.tree[i * 2 + 1] 


    def update(self, i: int, val: int) -> None:
        i += self.n
        self.tree[i] = val
        while i:
            left, right = i, i
            if i % 2:
                left = i - 1
            else:
                right = i + 1
            self.tree[i // 2] = self.tree[left] + self.tree[right]
            i //= 2

    def sumRange(self, i: int, j: int) -> int:
        i += self.n
        j += self.n
        sum = 0
        while i <= j:
            if i % 2:
                sum += self.tree[i]
                i += 1
            if not j % 2:
                sum += self.tree[j]
                j -= 1
            i //= 2
            j //= 2
        return sum