leetcode(32)前缀和系列题目

303. 区域和检索 - 数组不可变

记录前i个元素的和,因此sum[left,right + 1]=pre[right + 1]-pre[left]

class NumArray:

    def __init__(self, nums: List[int]):
        self.pre_sum = [0]
        for i in range(len(nums)):
            self.pre_sum.append(self.pre_sum[i] + nums[i])

    def sumRange(self, left: int, right: int) -> int:
        return self.pre_sum[right + 1] - self.pre_sum[left]


# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)

1856. 子数组最小乘积的最大值

前缀和+单调栈

class Solution:
    def maxSumMinProduct(self, nums: List[int]) -> int:
        pre_sum = [0]
        for i in range(len(nums)):
            pre_sum.append(nums[i] + pre_sum[i])
        res = 0
        nums = [-inf] + nums + [-inf]
        stack = []
        for r, n in enumerate(nums):
            while stack and nums[stack[-1]] > n:
                i = stack.pop()
                # print(nums[i])
                # print(nums[stack[-1]:r])
                cur = nums[i] * (pre_sum[r - 1] - pre_sum[stack[-1]])  # 注意r-1
                res = max(res, cur)
            stack.append(r)
        return res % (10 ** 9 + 7)

238. 除自身以外数组的乘积

前缀积 * 后缀积

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)
        pre = [1]
        for i in range(n - 1):
            pre.append(pre[i] * nums[i])
        # print(pre)
        tail = [1] * n
        for j in range(n - 2, -1, -1):
            tail[j] = tail[j + 1] * nums[j + 1]
        # print(tail)

        res = []
        for i in range(n):
            res.append(pre[i] * tail[i])
        return res

1732. 找到最高海拔

自己的写法:

class Solution:
    def largestAltitude(self, gain: List[int]) -> int:
        gain = [0] + gain
        res = gain[0]
        cur = 0
        for g in gain:
            cur += g
            res = max(res, cur)
        return res 

简洁写法:

class Solution:
    def largestAltitude(self, gain: List[int]) -> int:
        res = max(accumulate(gain,initial = 0))
        return res

813. 最大平均值和的分组

dp[i][j] 表示 \(\textit{nums}\) 在区间 \([0, i-1]\) 被切分成 j 个子数组的最大平均值和

class Solution:
    def largestSumOfAverages(self, nums: List[int], k: int) -> float:
        pre_sum = list(accumulate(nums, initial = 0))
        # print(pre_sum)
        n = len(nums)
        dp = [[0] * (k + 1) for _ in range(n + 1)]
        for i in range(1, n + 1):  # 前i个数全部分成1组
            dp[i][1] = pre_sum[i] / i
        for j in range(2, k + 1):  # 分成j组
            for i in range(j, n + 1):  # 前i个数
                for x in range(i):  # 前x个数分成j-1组 + [x-i]这1组
                    dp[i][j] = max(dp[i][j], dp[x][j-1] + (pre_sum[i] - pre_sum[x]) / (i-x))
        return dp[n][k]

1769. 移动所有球到每个盒子所需的最小操作数

分别计算前缀和和后缀和

class Solution:
    def minOperations(self, boxes: str) -> List[int]:
        n = len(boxes)
        left, right = [0] * n, [0] * n
        cnt = 0
        for i in range(1, n):
            if boxes[i - 1] == '1':
                cnt += 1
            left[i] = left[i - 1] + cnt
        cnt = 0
        for i in range(n-2, -1, -1):
            if boxes[i + 1] == '1':
                cnt += 1
            right[i] = right[i + 1] + cnt
        return [a + b for a, b in zip(left, right)]

posted @ 2022-10-28 16:13  YTT77  阅读(8)  评论(0编辑  收藏  举报