给定一个N个数的数组,求出所有长度的序列在R范围内的个数
Given an array of N numbers,find the number of sequences of all lengths having the range of R?
这是给定一个N个数字的序列,提取长度为K且范围小于R的序列的数量的后续问题?
我基本上需要向量v作为大小为N的答案,使得v[I]表示长度为I的序列的数量=R.
传统上,在递归解中,您会计算K=0,K=1的解,然后在后续元素之间找到某种递归关系,以避免每次从头开始重新计算解。
然而,在这里,我相信也许从另一边攻击这个问题会很有趣,因为传播的性质:
给定一个扩频R(或更小)的序列,任何子序列的扩频也低于R
因此,我将首先建立一个从每个索引开始的排列R的最长子序列的列表。让我们将这个列表称为M
,并具有M[i] = j
,其中j
是S
(原始序列)中S[j] - S[i] <= R
的较高索引。这将是O(N)。
现在,对于任何i
,从i
开始的长度为K
的序列的数量是0
或1
,并且这取决于K
是否大于M[i] - i
。通过对M
(从0
到N-K
)的简单线性传递给出了答案。这又是O(N)。
因此,如果我们将V
称为结果向量,其中V[k]
表示S
中长度为K
的子序列的数量,其扩展小于R
,那么我们可以在M:上进行单次迭代
for i in [0, len(M)]:
for k in [0, M[i] - i]:
++V[k]
该算法很简单,但更新的数量可能相当惊人。在最坏的情况下,假设M[i] - i
等于N - i
,则为O(N*N)复杂度。你需要一个更好的数据结构(可能是对芬威克树的改编)来使用这种算法,从而降低计算这些数字的成本。
如果您正在寻找连续序列,请尝试递归执行:范围小于R的K-长度子序列集包含在(K-1)-长度子序列集中。
在K=0时,有N个解。每次增加K时,都会附加(resp.prepend)下一个(resp.previous)元素,检查其范围是否低于R,然后将其存储在一个集合中(寻找重复项!)或根据结果丢弃它。
如果认为在最坏的情况下,该算法的复杂度为O(n*n),尽管平均而言可能更好。
我认为Matthieu在寻找所有具有排列R的序列时有正确的答案。
由于你只寻找长度为K的序列,你可以做得更好一点。与其看从i开始的最大序列,不如看看从i开始长度为K的序列,看看它是否有范围R。对每个i都这样做,你就得到了所有长度为K、排列为R的序列。
您不需要浏览整个列表,因为长度为K的序列的最新起点是n-K+1。所以复杂性类似于(n-K+1)*K=n*K-K*K+K。对于K=1,这是n,对于K=n,它是n。对于K=n/2,它是n*n/2-n*n/4+n/2=n*n/2+n/2,我认为这是最大值。所以,当这仍然是O(n*n)时,对于K的大多数值,你会得到更好的结果。
从一个更简单的问题开始:计算序列的最大长度,从每个索引开始,其范围等于R。
为此,让第一个指针指向数组的第一个元素。增加第二个指针(也从数组的第一个元素开始),同时指针之间的序列的范围小于或等于R。将第二个指示器传递的每个数组元素推到由一对混合-最大堆栈组成的最小-最大队列,如本答案所述。当最小-最大队列报告的最大值和最小值之差超过R时,停止增加第二个指针,增加V[ptr2-ptr1]
,增加第一个指针(从最小-最大排队中删除它所指向的元素),并继续增加第二指针(控制范围)。
当第二个指针离开数组的边界时,为所有剩余的ptr1递增V[N-ptr1]
(相应的范围可以小于或等于R)。要将小于R的所有其他范围相加,请从数组的末尾开始计算数组V[]的累积和。
时间复杂性和空间复杂性都是O(N)。
伪代码:
p1 = p2 = 0;
do {
do {
min_max_queue.push(a[p2]);
++p2;
} while (p2 < N && min_max_queue.range() <= R);
if (p2 < N) {
++v[p2 - p1 - 1];
min_max_queue.pop();
++p1;
}
} while (p2 < N);
for (i = 1; i <= N-p1; ++i) {
++v[i];
}
sum = 0;
for (j = N; j > 0; --j) {
value = v[j];
v[j] += sum;
sum += value;
}
- 不计算一个范围内的完美数
- 我有一个数组,我想输入一个范围,然后找到范围内所有偶数的总和?
- 检查IP是否在其他IP网络范围内,并查找下一个可用IP
- 从大范围内生成一个随机数,但从大范围的中间开始生成较小的范围
- 为什么C++找不到布尔运算符,当有一个!范围内的运算符?
- C :在一个范围内计数偶数 /奇数
- 如何创建一个结构的实例,当它不在范围内时,该实例将不会被删除
- 如果地图擦除范围内的第一个和最后一个相等,则是否删除该元素
- 是否可以在全球范围内声明一个提升线程
- 如何使用Linux GetRandom系统调用来在范围内生成一个随机数
- 如何调用其原型在另一个函数中范围内的函数
- 编写一个程序,该程序在0-99范围内生成10000个随机整数,并从随机数据中产生直方图
- 使用谷歌测试期望一个给定范围内的值
- 在一个范围内的阵列中找到三胞胎
- 需要在指定范围内生成一个随机整数
- 给定一个N个数的数组,求出所有长度的序列在R范围内的个数
- 如何检查一个范围内的值是否是另一个范围内的值的倍数
- 正在检查排序列表中是否有一个范围内的数字
- 有一个标准的算法可以在一个范围内迭代吗
- 是否可以编写一个在函数范围内使用时会抱怨的宏