当前位置: 首页 > 知识库问答 >
问题:

线性时间内所有子阵列的最大值之和乘以其长度

南门承教
2023-03-14

给定一个数组,我应该在线性时间内计算以下和:

我最天真的实现是O(n3):

sum_ = 0

for i in range(n):
    for j in range(n, i, -1):
        sum_ += max(arr[i:j]) * (j-i)

我不知道该怎么办。我尝试了很多算法,但它们最多只能是O(n*log(n)),但我应该在线性时间内解决它。还有,我不明白,有没有一种数学方法可以只看一个数组,然后告诉上面的和的结果?

共有1个答案

姬和豫
2023-03-14

保留一堆非递增值(索引)。因此,在追加新值之前,请弹出较小的值。每当你弹出一个,把它的贡献加到总数上。

def solution(arr):
    arr.append(float('inf'))
    I = [-1]
    total = 0
    for i in range(len(arr)):
        while arr[i] > arr[I[-1]]:
            j = I.pop()
            a = j - I[-1]
            b = i - j
            total += (a+b)*a*b//2 * arr[j]
        I.append(i)
    arr.pop()
    return total

条形图表示值,值越大,条形图越大。即将添加i处的值。浅灰色的比较晚。绿色的在堆栈上。棕色的已经不再起作用了。首先,弹出i-1的一个,但信息量较小。然后弹出j处的一个。它控制着I[-1]和I之间的范围:它是包含它的所有子阵列中的最大值。这些子阵列在左侧包含多个元素,在右侧包含多个元素。这就是a*b子阵列,它们的平均长度是a/b/2。

我暂时将无穷大附加到值,以便它在左侧作为哨兵(避免在while条件中进行额外检查)并在末尾作为清理器(它导致所有剩余值从堆栈中弹出)。非Python-coders:Python支持负索引,-1表示“最后一个元素”(从末尾开始的第一个)。

使用500个值的随机列表进行正确性测试(在线尝试!):

import random

def reference(arr):
    n = len(arr)
    return sum(max(arr[L : R+1]) * (R - (L-1))
               for L in range(n)
               for R in range(L, n))

for _ in range(5):
    arr = random.choices(range(10000), k=500)
    expect = reference(arr)
    result = solution(arr)
    print(result == expect, result)

示例输出(五个列表的结果,True表示它是正确的):

True 207276773131
True 208127393653
True 208653950227
True 208073567605
True 206924015682
 类似资料:
  • 例如:如果数组是[9,8,7,6,5,4,3,1,2,2],它应该返回46(长度为7的子数组[9,8,7,6,5,4,3]和长度为2的子数组[2,2]之和)。不能组合[9,8,7,6,5,4,3]和[1,2,2],因为这将产生长度为10的非素数的连续子数组(幂等性)。 有谁能解释一下如何使用DP来解决这类问题吗?多谢了。

  • 给出了一个长度为n的数组。求子数组元素的乘积之和。 解释 长度为3的数组A=[2,3,4]。 因为,对于以模1000000007计算的较长的子数组,乘积可以更大。 对于所有可能长度的子数组,即1,2,3,....,n,求这些和的有效方法是什么,其中n是数组的长度。

  • 问题内容: 我试图从表中获取所有列的列表,这些列表包含它们的数据类型,数据长度和该列中最长值的长度。 我使用此SQL来获取列及其数据类型和长度: 我有此SQL,用于获取值的最大长度: 但是我不知道如何将它们结合起来。我正在使用SQL Server 2008。 问题答案: 感谢您的建议。我想出了以下解决方案。它为我获取了我需要的数据,但是希望了解它是否可以提高效率。

  • 有人能为下面的问题提出一个简单的解决方案吗? 最长子数组:查找子数组中元素之和小于或等于“k”的最长连续子数组的长度。 输入为:< code>array和< code>k。 例子: 输出: 2个 解释: 子数组:{1},{2},}3},1,2},2,3},{1,2,3} {1,2} =

  • 我正在考虑这个leetcode问题,在完成这个天真的方法时遇到了一个问题。我在这里找到了一个最佳的解决方案。但我不确定我天真的尝试到底出了什么问题。 问题如下: 给定两个整数数组A和B,返回两个数组中出现的子数组的最大长度。 示例: 输入:A:[1,2,3,2,1]B:[3,2,1,4,7] 输出:3 说明:最大长度的重复子数组为[3,2,1]。 这是我当前的代码: 我的解决方案通过了几个测试用例

  • 给定一个整数数组,包含不超过两个不同值的最长子数组的长度是多少,使得非重复值的差异不超过 1? 例: 最大的子数组长度为4:[1,2,1,2]。 最大的子阵列具有长度4:[3,3,2,2]。值1和3相差1以上,因此[1,1,1,3,3]无效。