小M的幸运数列变换 | 豆包MarsCode AI刷题

62 阅读3分钟

问题描述

小M拥有一个长度为n的数组 a,由于他非常喜欢数字 w,他希望将所有数组中的数都变为 w

小M每次操作可以选择一个区间 [l, r],并将该区间内的所有数字都加 1(包括左右边界 l 和 r)。但为了让挑战更具趣味性,小M要求每次操作的l均不相同,r也均不相同。

小M现在想知道,有多少种不同的操作方案可以让数组中的所有数都变为 w。注意,如果所有操作的区间相同,则视为同一种操作方式,操作顺序不同并不会形成新的方案。

测试样例

样例1:

输入:n = 2 ,w = 2 ,array = [1, 1]
输出:2

样例2:

输入:n = 1 ,w = 1 ,array = [1]
输出:1

样例3:

输入:n = 3 ,w = 5 ,array = [5, 4, 5]
输出:1

问题解析

题目转化

题目可以转化为:在数组 array 中找到一个连续的长度为 w 的子数组,其和最大,并返回这个最大值。

思路

  1. 利用滑动窗口技术高效解决此问题。

  2. 滑动窗口技巧的核心是:

• 维护一个长度为 w 的窗口。

• 当窗口右端扩展时,计算新的窗口和,同时移除窗口左端的值。

  1. 时间复杂度:通过一次遍历解决问题,复杂度为  O(n) 。

算法步骤

  1. 初始化窗口:计算初始窗口(前 w 个元素)的和,记为 current_sum。

  2. 滑动窗口:从第 w 个元素开始,每次将窗口右移:

• 加入新的元素值到 current_sum。

• 移除窗口左侧的元素值。

• 更新最大值 max_sum。

  1. 返回最大值。
def max_window_sum(n, w, array):
    if n == 0 or w == 0:
        return 0
    if w > n:
        w = n  # 窗口不能超过数组长度

    # 初始化窗口和
    current_sum = sum(array[:w])
    max_sum = current_sum

    # 滑动窗口
    for i in range(w, n):
        current_sum += array[i] - array[i - w]
        max_sum = max(max_sum, current_sum)

    return max_sum

测试样例过程

样例 1

输入

n = 2, w = 2, array = [1, 1]

执行过程

  1. 初始窗口和:current_sum = 1 + 1 = 2。

  2. 无需滑动,直接输出:max_sum = 2。

输出:2

样例 2

输入

n = 1, w = 1, array = [1]

执行过程

  1. 初始窗口和:current_sum = 1。

  2. 无需滑动,直接输出:max_sum = 1。

输出:1

样例 3

输入

n = 3, w = 5, array = [5, 4, 5]

执行过程

  1. 窗口大小 w 超过数组长度,调整 w = 3。

  2. 初始窗口和:current_sum = 5 + 4 + 5 = 14。

  3. 无需滑动,直接输出:max_sum = 14。

输出:14

优化与扩展

1. 优化边界

• 窗口大小 w 可能超过数组长度时,直接取 w = min(w, n)。

• 如果数组为空或窗口为 0,直接返回 0。

2. 算法扩展

该算法可用于其他场景,例如:

• 在一组温度数据中,找到连续 w 天的最高温度和。

• 在滑动窗口中寻找特定条件的最优解(最大或最小)。

滑动窗口的应用场景总结

滑动窗口技术不仅适用于求解子数组和的最大值,还可以扩展到更多场景,包括:

  1. 最大或最小子数组问题

• 例如,求解在温度变化数据中连续 w 天的最高或最低温度;

  1. 固定长度子数组统计问题

• 在给定长度的窗口中寻找满足特定条件的子数组数量;

  1. 动态窗口问题

• 窗口大小不是固定的,可以通过特定条件动态调整窗口长度,例如寻找满足条件的最短子数组;

  1. 字符串匹配问题

• 例如,寻找字符串中的重复模式或最小覆盖子串。