给定一个有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
如果列表被排序,您可以考虑大小为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)
> < li>
让我们修复一个元素(< code>a[i])。我们想知道比位于< code>i(L
)左边的元素小的最右边元素的位置。我们还需要知道比位于< code>i(R
)右侧的元素小的最左侧元素的位置。
如果我们知道L
和R
,我们应该在答案中添加(i - L)* (R - i)* a[i]
。
可以使用堆栈在线性时间内为所有i
预计算L
和R
。伪代码:
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}是结果子数组。