181. 差分数组学习

1.查分数组

1.首先名字看起来很高大上其实呢就是前一项减后一项, 不用怕
举个例子: 
list1 = [2, 5, 4, 9, 7, 10, 0]
list1 = [0, 2, 5, 4, 9, 7, 10, 0]  # 最前面补一个零(因为第一项没有前一个元素)
diff_list = []
for i in range(1, len(list1)):
    diff_list.append(list1[i] - list1[i-1])  # 前一项减去后一项
print(diff_list)  
# 结果就是这个样子, 他能干嘛呢? 发现没有如果给diff_list计算前缀和刚好就是原数组
diff_list = [2, 3, -1, 5, -2, 3, -10]

2.计算前缀和(可能你不相信我说前缀和就是他的原数组没关系,算一遍)
size = len(diff_list)
list2 = [0 for _ in range(size +1)]
for i in range(1, size + 1):  # 这里是为了计算前缀和数组
    list2[i] = list2[i-1] + diff_list[i-1]
print(list2)
[0, 2, 5, 4, 9, 7, 10, 0]  你看看他想不想list1也就是原数组
这个时候你明白了差分数组的其中一个作用了把?计算前缀和还原数组

3.产品听需求了,我们需要给
	1. [1, 4]的数值全部加上3
    2. 上面条件的基础上[3, 5] 减去5
是不是感觉很简单? 遍历一遍加上去就可以了,但是如果如果数量级比较大1e5你1000ms可以过去么? 很不幸我在力扣里面超时了.

这时候就需要利用差分数组的性质了: 将原始数组中元素同时加上或者减掉某个数,那么他们的差分数组其实是不会变化的
没事不懂咋就举例子: 
list1 =     [0, 2, 5, 4, 9, 7, 10, 0]  原数组
diff_list = [2, 3, -1, 5, -2, 3, -10]  差分数组

[1, 4]的数值全部加上3
如果我们给差分数组1索引位置元素+3, 4+1=5所以位置-3会造成什么?
diff_list = [2, 3+3, -1, 5, -2, 3-3, -10]

# 说话你们不信, 直接看代码, 结果[0, 2, 8, 7, 12, 10, 10, 0], 看到了什么[1,4]+3了, 其他数据没影响是不是很完美.(0是我们加的辅助数字不需要管)
diff_list = [2, 3+3, -1, 5, -2, 3-3, -10]
size = len(diff_list)
list2 = [0 for _ in range(size +1)]
for i in range(1, size + 1):  # 这里是为了计算前缀和数组
    list2[i] = list2[i-1] + diff_list[i-1]
print(list2)  # [0, 2, 8, 7, 12, 10, 10, 0]

上面条件的基础上[3, 5] 减去5 # 经过上面我相信你已经明白了,如果需要修改[x,y]位置元素大小只需要给x位置+对应数字, y+1位置-对应数组即可(相信减法你可以理解),进行第二个条件
diff_list = [2, 3+3, -1, 5-5, -2, 3-3, -10+5]
size = len(diff_list)
list2 = [0 for _ in range(size +1)]
for i in range(1, size + 1):  # 这里是为了计算前缀和数组
    list2[i] = list2[i-1] + diff_list[i-1]
print(list2)  # [0, 2, 8, 7, 12, 10, 10, 0]
[0, 2, 8, 7, 12, 10, 10, 0]  # 条件1结果
[0, 2, 8, 7, 7, 5, 5, 0]  # 条件2结果

# 防止你们不相信, 我暴力的修改也给出来, 如下
list1 = [2, 5, 4, 9, 7, 10, 0]
size = len(list1)
for i in range(size):
    if 1 <= i <= 4:
        list1[i] += 3

    if 3 <= i <= 5:
        list1[i] -= 5
print(list1)   # [2, 8, 7, 7, 5, 5, 0]


4.总结3写成代码diff_list差分数组  [x, y]位置加上同样大小的数m
diff[x] += m
diff[y+1] -= 1 # y+1需要小于数组长度n, len(diff_list)
注意 只能是区间元素同时增加或减少相同的数的情况才能用

5.实践开始,

1.题目1: HDU-1556 Color the Ball

说实话第一次遇到查分数组相关问这个气球搞得我很懵逼, 但是看了大佬的代码一下在就明白了?
我把这题根据力扣的题目改了一下:(还是返回气球总共修改了几次)
其中n表示气球数量, balls数组放置每次涂改颜色的区间(前后都包含)给你看个例子就好了
例1:
n = 3
balls = [[1, 1], [2,3], [3,3]]
结果 [1, 1, 1]
例2:
n = 3
balls = [[1, 1], [1,2], [1,3]]
结果 [3, 2, 1]  # 这个结果其实就是最后的差分数组,他记录了每个位置对应的气球修改的次数
代码如下:
def func(balls, n):
        a = [0 for _ in range(n+1)]  # 结果数组
        b = [0 for _ in range(n+1)]  # 差分数组

        for i in range(len(balls)):
            x, y = balls[i]
            b[x] += 1  # 1其实就是每次修改一遍
            if y < n:
                b[y+1] -= 1

        for i in range(1, n+1):
            a[i] = a[i-1] + b[i]  # 前缀和

        return a[1:]

1.题目二: 1109. 航班预订统计

这个题很题目一很类似, 上面统计修改次数, 这个题目统计座位数目. 只不过给区间加上了权重,也就是座位数
class Solution(object):
    def corpFlightBookings(self, bookings, n):
        """
        https://blog.csdn.net/qq_44786250/article/details/100056975  参考这个学习查分数组
        航班编号        1   2   3   4   5
        预订记录 1 :   10  10
        预订记录 2 :       20  20
        预订记录 3 :       25  25  25  25
        总座位数:      10  55  45  25  25
        :type bookings: List[List[int]]
        :type n: int
        :rtype: List[int]
        """
        a = [0 for _ in range(n+1)]
        b = [0 for _ in range(n+1)]

        for i in range(len(bookings)):
            x, y, w = bookings[i]
            b[x] += w  # 同样的代码加上权重就好了
            if y < n:
                b[y+1] -= w

        for i in range(1, n+1):
            a[i] = a[i-1] + b[i]

        return a[1:]
posted @ 2021-08-31 10:45  楠海  阅读(61)  评论(0编辑  收藏  举报