这个问题适用于真正的brainiacs,因为它应该在没有辅助数组的情况下完成 并且必须最有效率!
C程序 - 需要接收带有X数字的数组 (假设X = 4阵列:5,4,3,2) 并检查数组是否包含从0到X-1的所有数字 (如果X为44,则需要检查数组内是否有0到43之间的所有数字。)
它必须是超级高效的 - 我的意思是,在阵列上运行43次不是一种选择!
你知道怎么做吗?我试图在没有任何成功的情况下计算这个数字!!
必须是O(n)。
答案 0 :(得分:2)
如果允许更改数组的顺序,您可以使用就地排序算法,然后检查是否为某些i:
array[i] == array[i+1]
时间复杂度可以是O(n * lg n)。
答案 1 :(得分:1)
您可以简化问题以查找重复项。
证明:
有了这个,你可以使用这个实现:Finding duplicates in O(n) time and O(1) space。还要确保检查数组的边界。如果数字不在边界内,则数组包含不正确的数字。
这导致O(n)解决方案。
答案 2 :(得分:1)
对两个数组进行排序(位于O(n log n)
)。然后将两个数组视为队列:
答案 3 :(得分:0)
您可以对数组进行排序,然后扫描一次。这应该会给你O(N log N)的性能,优于你对天真的方法所需的O(N ^ 2)。
答案 4 :(得分:0)
查看一些精彩的答案here,@ caf的答案的C ++实现可能是
bool stop=true;
//首先将元素i放在位置A [i],即4位于A [4]
for(int i = 0; i<n; i++) {
while (A[A[i]] != A[i]){
swap(A[i], A[A[i]])
}
}
// than u can have the second loop which does the decision
for(int i = 0; i<n && !stop; i++) {
if (A[i] != i){
stop = true;
}
}
if (stop)
printf("duplicate");
else
printf("not duplicate)
答案 5 :(得分:0)
foreach(int i in array)
{
int count = 0;
foreach(int i2 in array)
{
if(i == i2)
{
count++;
}
}
if(count > 1)
{
return false;
}
}
return true;
答案 6 :(得分:0)
O(n)解决方案:算法尝试将数组中的每个元素放在其正确的位置,例如1到a [0]和2到a [1],通过与元素交换占据原点位置。
起初,i = 1,a [i - 1] = 1,没关系,什么都不会被触及
i = 1
a = 1 6 3 4 5 7 1
然后,i = 2,a [i - 1] = 6!= 2,然后交换a [i - 1]和[6 - 1]
i = 2
a = 1 7 3 4 5 6 1
然后,我仍然是2,但是[i - 1] == 7!= 2,然后交换[i - 1]和[7 - 1]
i = 2
a = 1 1 3 4 5 6 7
现在i = 2,但我们看到[i - 1] == a [1 - 1],因此我们找到重复的
完整来源:
#include <stdio.h>
int main() {
int a[7] = {1, 6, 3, 4, 5, 7, 1};
int i, t;
for (i = 0; i < 7; ++i) {
while (a[i] != i + 1) {
if (a[i] == a[a[i] - 1]) {
printf("duplicate: %d\n", a[i]);
goto out;
}
t = a[i];
a[i] = a[a[i] - 1];
a[t - 1] = t;
}
}
printf("no duplicate\n");
out:
return 0;
}
答案 7 :(得分:0)
如果数组都已排序,您可以使用修改后的合并操作(如mergesort中使用的那样)。
答案 8 :(得分:0)
您可以[建议平均情况]优于建议的O(nlogn)
解决方案。
使用哈希表有一个O(n)
机动平均案例解决方案:
hash <- new hash set
for each e in A:
hash.add(e)
for each e in B:
if hash.contains(e): print e
如果它们在B中出现两次,则可以通过存储额外的“打印”元素散列集来克服打印两次元素。
如果延迟或最坏情况的性能是一个问题,请使用建议的排序和迭代解决方案之一。
答案 9 :(得分:0)
对较小的进行排序并使用二进制搜索来搜索较大的每个元素。这样,您可以在O((n1+n2)*log(n1))
中执行此操作,其中n1, n2
是数组的大小(n1
更小)。
答案 10 :(得分:-1)
我不明白我在这个问题中缺少什么,但AFAIK我没有看到为什么任何(合理的)解决方案应该比O(n)
时间(和空间)更多/更差的原因复杂性。
从上述评论和答案中,我理解以下内容:
check if all the array has all the numbers from 0 to X-1
。因此,数组中不会出现小于0
的任何内容。所以我认为不允许使用负数check if all the array has all the numbers from 0 to X-1
我想如果X
是数组的大小,并且0
到X-1
的所有数字都应该在场,我想不允许重复的数字。因此,做出上述假设,我们可以使用一位来检查i
(0 <= i <= X-1
)是否存在。如果i
重复,则无法提及存在重复的数字。
它扫描整个数组一次 - O(n)
并且每个元素只使用一位,因此X
为10
需要X
位 - 例如,考虑我们需要处理1000000
元素而sizeof(int)
是4
然后我们需要3.82M
内存来保存数组元素,只有0.48M
用于存储一个元素。
#include <stdio.h>
#define X 10
#define MIN 0
#define MAX X-1
int main(void)
{
//int arr[X] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
//int arr[X] = {6, 7, 8, 9, 0, 5, 3, 2, 11, 12};
//int arr[X] = {1, 1, 2, 4, 5, 6, 7, 8, 2, 2};
int arr[X] = {1, 3, 2, 4, 5, 6, -7, 8, 2, 2};
/* if X is more than sizeof(int) then change
the flag type to a wider one! */
int flag = 0;
int i;
for(i=0 ;i<X ; i++) {
if (arr[i] >= MIN && arr[i] <= MAX) {
if (flag & 1<<arr[i]) {
printf("Duplicate found : %d \n", arr[i]);
return -1;
}
flag |= 1<<arr[i];
} else {
printf("Failure at %d : %d \n", i, arr[i]);
return -1;
}
}
printf("Success \n");
return 0;
}
答案 11 :(得分:-1)
阅读本文以获得答案 - array validation - without using an auxiliary array
n个元素的数组,其中包含从0到n-1的元素,这些数字中的任何一个都会出现任意次数。
例如,设n为7,数组为{1,2,3,4,5,4,6},答案应为FALSE
上述陈述不是自相矛盾吗?!