C 确定一个数组是否每一次都有数字a到b

C 确定一个数组是否每一次都有数字a到b,c,algorithm,permutation,C,Algorithm,Permutation,给定一个大小为n的数组A,以及两个b-A+1=n的数字A和b,我需要确定A是否包含A和b之间的每个数字(恰好一次) 例如,如果n=4,a=1,b=4,那么我想看看a是否是[1,2,3,4]的重排 实际上,我需要使用O(1)空间(没有哈希表)来完成这项工作 我的第一个想法是对A进行排序,但我必须在不重新排列A的情况下进行排序,所以就这样结束了 我的第二个想法是运行一次,将条目相加并检查它们是否在正确的范围内。最后,我必须得到正确的和(对于a=1,b=n,这是n(n+1)/2),但这并不总是能捕获所

给定一个大小为n的数组A,以及两个b-A+1=n的数字A和b,我需要确定A是否包含A和b之间的每个数字(恰好一次)

例如,如果n=4,a=1,b=4,那么我想看看a是否是[1,2,3,4]的重排

实际上,我需要使用O(1)空间(没有哈希表)来完成这项工作

我的第一个想法是对A进行排序,但我必须在不重新排列A的情况下进行排序,所以就这样结束了

我的第二个想法是运行一次,将条目相加并检查它们是否在正确的范围内。最后,我必须得到正确的和(对于a=1,b=n,这是n(n+1)/2),但这并不总是能捕获所有内容,例如,[1,1,4,4,5]通过了n=5,a=1,b=5的测试,但不应该


我唯一有效的想法是通过数组n次,确保每个数字都只出现一次。有更快的解决方案吗?

您只需对前面提到的
n(n+1)/2
方法稍作修改,就可以通过阵列进行单次扫描

为此,遍历数组,忽略a..b范围之外的元素。对于正确范围内的数字,您希望跟踪三个值:数字之和、数字平方和以及数字计数

您可以预先计算数字和平方和(以及计数)的正确值

然后将结果与预期结果进行比较。例如,如果你搜索1, 2, 3,4。如果你只使用数字的和,那么[1,1,4,4]将产生正确的结果(1+2+3+4=10,1+1+4+4=10),但是如果你也加上平方和,问题很明显:1+4+9+16=30,但1+1+16+16=34

这实质上是对问题应用(至少非常类似)布鲁姆过滤器。给定一个足够大的组和一对固定的函数,将有一些不正确的输入集产生正确的输出。通过增加应用的过滤器数量,可以将这种可能性降低到任意低的值。或者,你也可以设计一个不被愚弄的自适应算法——如果你的输入范围是N,那么将每个数字的幂提高到N+1,可能会确保你只能用正确的输入得到正确的结果(但我承认,我不能绝对肯定这是正确的).

以下是一个O(1)空间和O(n)解决方案,可能会有所帮助:-

  • 在范围(a,b)中找到
    平均值
    标准偏差
  • 扫描阵列并找到平均值和标准偏差
  • 如果任何数字在(a,b)之外,则返回false
  • if(mean1!=mean2 | | sd1!=sd2)返回false,否则返回true。

  • 注意:我可能不是100%准确。

    这里有一个解决方案失败,可能会发生哈希冲突

    以一个优秀的(例如加密)散列函数H为例

    Compute: xor(H(x) for x in a...b)
    Compute: xor(H(A[i]) for i in 1...n)
    
    如果两者不同,那么肯定没有排列。如果两者是相同的,那么你几乎肯定会得到一个排列。通过在散列中包含一个随机种子,您可以使其不受为产生散列冲突而拾取的输入的影响


    这在运行时显然是O(b-a),需要O(1)个外部存储,实现起来很简单。

    n有多大?为什么要求O(1)空间?听起来像是面试问题,而不是面试问题或家庭作业。对于大小,n可以增加到10^9或更多。我的解决方案是可行的,但必须有更好的方法。执行顺序
    O((b-a)*n)
    (最坏情况)是否符合您的期望?另请参见:对于n大(甚至100)来说,这一点都不太准确。@Daniel我认为这不取决于n的大小,而更取决于数字的分布这对于较小的n来说是个好主意,但将数字提高到10^9并不容易。@Daniel:视情况而定。有一些方法(例如,在RSA加密中广泛使用)可以有效地将数字提高到大的幂次。简单的例子是:集合6,5,1和7,3,2的计数、和和和以及平方和都相等。