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

时间:2014-01-26 04:36:05

标签: c algorithm permutation

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

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

实际上,我需要使用O(1)空间(没有哈希表)来执行此操作。

我的第一个想法是对A进行排序,但是我必须在不重新排列A的情况下这样做,这样才能解决。

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

我的唯一想法是通过数组n次,确保每次只能查看一次。有更快的解决方案吗?

3 个答案:

答案 0 :(得分:3)

只需对您已经提到的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的幂可能会确保你只能得到正确的结果是正确的输入(但我承认,我并不完全确定这是正确的。)

答案 1 :(得分:0)

这是一个可能有用的O(1)空间和O(n)解决方案: -

  1. 在范围(a,b)
  2. 中找到meanstandard deviation
  3. 扫描阵列并找出平均值和标准偏差。
  4. 如果有任何数字在(a,b)之外,则返回false
  5. if(mean1!=mean2 || sd1!=sd2) return false else true.
  6. 注意:我可能不是100%准确。

答案 2 :(得分:0)

这是一个以哈希冲突概率失败的解决方案。

采用优秀的(例如加密)哈希函数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)外部存储,并且实现起来很简单。