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

连续序列的和

赫连子石
2023-03-14

给定一个有N个元素的数组A,我想在A的所有可能的连续子序列中找到最小元素的总和。我知道如果N很小,我们可以寻找所有可能的子序列,但是当N高达10^5时,找到这个总和的最佳方法是什么?

示例:设 N=3 且 A[1,2,3] 则 ans 为 10,作为可能的连续子序列 {(1),(2),(3),(1,2),(1,2,3),(2,3)} 因此最小元素之和 = 1 2 3 1 1 2 = 10

共有2个答案

阙星渊
2023-03-14

如果列表被排序,您可以考虑大小为1、2、3到N的所有子集。该算法最初有点低效,但下面是优化版本。这是一些伪代码。

let A = {1, 2, 3}
let total_sum = 0

for set_size <- 1 to N
    total_sum += sum(A[1:N-(set_size-1)])

首先,用一个元素设置:{{1}、{2}、{3}}:对每个元素求和。

然后,两个元素的集合{{1,2},{2,3}}:对除最后一个元素之外的每个元素求和。

然后,三个元素的集合{{1,2,3}}:将每个元素相加,但最后两个元素相加。

但是这种算法效率很低。要优化到O(n),将每个第I个元素乘以N-i并求和(此处从零开始索引)。直觉是第一个元素是N个集合的最小值,第二个元素是N-1个集合的最小值,以此类推。

我知道这不是一个python问题,但有时代码会有所帮助:

A = [1, 2, 3]

# This is [3, 2, 1]
scale = range(len(A), 0, -1) 

# Take the element-wise product of the vectors, and sum
sum(a*b for (a,b) in zip(A, scale))

# Or just use the dot product
np.dot(A, scale)
郏扬
2023-03-14

> < li>

让我们修复一个元素(< code>a[i])。我们想知道比位于< code>i(L)左边的元素小的最右边元素的位置。我们还需要知道比位于< code>i(R)右侧的元素小的最左侧元素的位置。

如果我们知道LR,我们应该在答案中添加(i - L)* (R - i)* a[i]

可以使用堆栈在线性时间内为所有i预计算LR。伪代码:

s = new Stack
L = new int[n]
fill(L, -1)
for i <- 0 ... n - 1:
    while !s.isEmpty() && s.top().first > a[i]:
        s.pop()
    if !s.isEmpty():
        L[i] = s.top().second
    s.push(pair(a[i], i))

我们可以反转数组并运行相同的算法来查找R

如何处理相等元素?让我们假设a[i]是一对

时间复杂度为 O(n)。

这是一个完整的伪代码(我假设int可以在这里保存任何整数值,您应该选择一种可行的类型以避免真实代码中的溢出。我还假设所有元素都是不同的):

int[] getLeftSmallerElementPositions(int[] a):
    s = new Stack
    L = new int[n]
    fill(L, -1)
    for i <- 0 ... n - 1:
        while !s.isEmpty() && s.top().first > a[i]:
            s.pop()
        if !s.isEmpty():
            L[i] = s.top().second
        s.push(pair(a[i], i))
    return L

int[] getRightSmallerElementPositions(int[] a):
    R = getLeftSmallerElementPositions(reversed(a))
    for i <- 0 ... n - 1:
        R[i] = n - 1 - R[i]
    return reversed(R)

int findSum(int[] a):
    L = getLeftSmallerElementPositions(a)
    R = getRightSmallerElementPositions(a)
    int res = 0
    for i <- 0 ... n - 1:
        res += (i - L[i]) * (R[i] - i) * a[i]
    return res

 类似资料:
  • NowCoder 题目描述 输出所有和为 S 的连续正数序列。 例如和为 100 的连续序列有: // [9, 10, 11, 12, 13, 14, 15, 16] [18, 19, 20, 21, 22]。 解题思路 // java public ArrayList<arraylist> FindContinuousSequence(int sum) { ArrayList<arr

  • 问题内容: 如果我有串,我要检查,如果它作为一个连续存在 串 中,我可以使用: 在非连续子 序列 的情况下,我可以使用什么?例: 问题答案: 我不知道是否有内置功能,但是手动操作相当简单

  • 我试图在Oracle 11g中运行一个sql查询,它将下面给定的数据集转换为下一个数据集。 这样做的逻辑是start date1和end date1将是连续的。另外start_date2和end date2需要是连续的。如果在某些时候end date2与下一个start date2不匹配,那么需要添加一个具有相同id并且具有enddate2作为下一个start date1的新行。 非常感谢您的帮助

  • 一、题目 输入一个正数s,打印出所有和为s 的连续正数序列(至少两个数)。 举例说明 例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打出3 个连续序列1~5、4~6 和7~8。 二、解题思路 考虑用两个数small 和big 分别表示序列的最小值和最大值。首先把small 初始化为1, big 初始化为2。如果从small 到big 的序列的和大于s,我们可以从序列中去掉

  • 此用例是一项服务,它手动将一系列未压缩的. wav媒体段编码为. m4s片段以通过MPEG-DASH广播,使用ffmpeg将. wav压缩为. aac和sannies/mp4parser将aac音频组装成. m4s媒体片段。 我创建了这个公共GitHub项目来完整地再现该问题。 例如,这是自定义的ChunkFragmentM4sBuilder.java类。 此日志来自ChunkFragmentM4

  • {4,5,1,5,7,6,8,4,1},答案是5。 对于第一个例子,子数组{5,3,1,4,2}排序后可以形成连续序列1,2,3,4,5,它们是最长的。 对于第二个示例,子数组{5,7,6,8,4}是结果子数组。