数组验证 - 不使用辅助数组

时间:2012-01-03 09:45:48

标签: c arrays logic memory-efficient

这个问题适用于真正的brainiacs,因为它应该在没有辅助数组的情况下完成 并且必须最有效率!

C程序 - 需要接收带有X数字的数组 (假设X = 4阵列:5,4,3,2) 并检查数组是否包含从0到X-1的所有数字 (如果X为44,则需要检查数组内是否有0到43之间的所有数字。)

它必须是超级高效的 - 我的意思是,在阵列上运行43次不是一种选择!

你知道怎么做吗?我试图在没有任何成功的情况下计算这个数字!!

必须是O(n)。

12 个答案:

答案 0 :(得分:2)

如果允许更改数组的顺序,您可以使用就地排序算法,然后检查是否为某些i:

array[i] == array[i+1]

时间复杂度可以是O(n * lg n)。

答案 1 :(得分:1)

您可以简化问题以查找重复项。

证明:

  • 如果阵列的长度不是X =>有数字丢失。您可以在O(1)或O(n)中轻松检查。
  • Else =>你有所有正确的数字或​​有重复数。

有了这个,你可以使用这个实现:Finding duplicates in O(n) time and O(1) space。还要确保检查数组的边界。如果数字不在边界内,则数组包含不正确的数字。

这导致O(n)解决方案。

答案 2 :(得分:1)

对两个数组进行排序(位于O(n log n))。然后将两个数组视为队列:

  1. 如果两个队列的头元素相等,则打印其中一个并弹出两个队列。
  2. 如果头元素不相等,则弹出较小的元素。
  3. 重复。

答案 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)时间(和空间)更多/更差的原因复杂性。

从上述评论和答案中,我理解以下内容:

  • 负数:我不确定是否允许负数。 OP说check if all the array has all the numbers from 0 to X-1。因此,数组中不会出现小于0的任何内容。所以我认为不允许使用负数
  • 重复的数字:引用OP的相同引用 - check if all the array has all the numbers from 0 to X-1我想如果X是数组的大小,并且0X-1的所有数字都应该在场,我想不允许重复的数字。

因此,做出上述假设,我们可以使用一位来检查i0 <= i <= X-1)是否存在。如果i重复,则无法提及存在重复的数字。

它扫描整个数组一次 - O(n)并且每个元素只使用一位,因此X10需要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

上述陈述不是自相矛盾吗?!