marscode刷题 数组操作次数计算 | 豆包MarsCode AI刷题

120 阅读4分钟

数组操作次数计算

题目用python通过,如有需要请用ai转义成其他代码,由于这道题用数学解答,代码没有太复杂,看看自己写也成。


题目如下:小C得到了一个数组,他要对这个数组进行一些操作,直到数组为空。每次操作时,他会执行以下步骤:

  1. 如果数组的第一个元素 a[0] 等于0,则直接删除 a[0],并将数组中剩余的所有元素向左移动以填补空缺。
  2. 否则,将 a[0] 个 a[0]-1 添加到数组末尾,并将 a[0] 减少1。

小C想知道,在进行这些操作直到数组为空时,总共进行了多少次操作。结果需要对 109+7109+7 取模。


解题思路: 第一思路当然是暴力模拟。先考虑下模拟行不行。
首先考虑模拟题意进行写代码。对第一个数进行判断,如果是0,直接pop。如果不是0,那么按照题意进行操作,把 a[0] 个 a[0] - 1加到数组末尾。

再思考一下用什么数据结构,对开始的删除,末尾的加入,在python里选deque就好。

那么接下来写模拟的代码,或者让marscode生成模拟的代码, 如果没有意外地话,会tle。 这道题时间不允许直接暴力。

如果不是直接暴力,那么有没有在模拟情况下优化的点呢? 仔细思考一下会发现, 非零情况下没必要每次都加入末尾,加到当前数的后边也是可以的。因为数组的处理顺序在这里并没有强制的要求。

既然可以加入到这个数的末尾,与数组的顺序无关,而且每次的操作都有很强的数学关系,这道题的标签是数学。那么这引导我们去想一个角度, 能不能用一个通用的数学公式去推导一下, 看是不是有更加优化的解决方法,使得这道题不会超时。


第二思路: 用数学模拟。

在考虑用数学模拟之后,当然是让marscode帮我看下有没有规律啊(有ai帮我写,我就可以偷个懒,歇一歇

结果发现, 欸嘿嘿, Marscode的代码竟然没有通过, 看来还得训练下数学公式的推导。

那只能手推了, 不能偷懒哈哈哈。


想一下规律:
如果第一个数是 0 ,那么需要操作 1 次把 0 删去 。

如果第一个数是 1 , 那么需要把 1 变成0 , 另外在这个数后边加上a[0] 个a[0] - 1, 即加上 1 个 0 。 那么此时变成了 两个 0 。 这种情况下需要 处理 2 次 0 的情况才算结束。 一共处理了 3 次

再推一下第一个数是 2 的情况,第一次操作需要把 2 变成 1, 在这个数之后加入 2 个 1, 这样操作一次后是 3 个 1 。 此时只需要再加上 3 个 1 的操作次数, 一共操作课 10 次。


这样思路清晰了,规律耶可以推出来了。
每操作一个数 , 假设为 x ,先判断是否为0 , 不是 0 的情况下要先操作一次变成 x - 1, 再 加上 x 个 x - 1 。 这样操作一次后变成了 x + 1 个 x - 1 。 只需要再加上 x + 1 个 x - 1的次数就好了。

操作之后与x - 1有关,那么可以预处理一下。

0 的操作次数 是 1 1 的操作次数 是 1 + (1 + 1)个0的操作次数 。。。。。

那么预处理的代码为:

f = [1]
for i in range(1, 1000):
    f.append(1 + (i + 1) * f[-1])

这样的话我们只需要遍历这个数组, 再把当前的结果加入答案即可, 嘿嘿

当然最后不要忘了 还有一个 mod 哦!!!


完整代码如下:

 MOD = 10**9 + 7
 f = [1]
 for i in range(1, 1000):
     f.append(1 + (i + 1) * f[-1])
def solution(n: int, a: list) -> int:
    n = len(a)
    result = 0

    for x in a:
        result = (result + f[x]) % MOD

    return result

嘿嘿,这样就写完了, 总结一句, marscode还得练!!!