创建一个n个数字的数组,有效地排除k个给定数字

时间:2015-01-07 20:11:59

标签: c arrays

如何创建一个从1开始到n结尾的数字数组,而不包括数组中给定的k个数字?例如,n = 10 k = 2,k的两个数字是3和6,那么我的数组是1,2,4,5,7,8,9,10。

我必须为像

这样的大数字做这件事

1< n< 10 ^ 9

然后

0< k<分(10 ^ 5,n)的

对于较小的数字,我尝试索引,然后将其存储在一个不同的数组中,占用了大量的空间和时间。我怎样才能有效地完成它?

            scanf("%lld%lld",&n,&k);
            f=0;
            long long int a[100010]={0};
            long long int b[100010]={0};
            for(i=0;i<k;i++)
            {
            scanf("%lld",&temp);
            a[temp]=-1;
            }
            for(i=0;i<n+1;i++)
            {
                if(a[i]!=-1)
                {
                b[f++]=i;
                }
            }

1 个答案:

答案 0 :(得分:0)

使用n作为范围的结尾,k作为跳过的数字的数量,narr作为保存结果的数组,karr作为数组保持要跳过的数字:karr只需要k个元素。如果对karr进行了排序,则只需将每个新号码与karr中的一个元素进行比较,然后在匹配时移至下一个karr,并将新号码添加到narr他们什么时候没有。以下示例显示了这一点(但没有错误检查):

#include <stdlib.h> // for malloc and qsort
#include <stdio.h>  // for printf

// compare function for qsort
static int llcompare(const void *a, const void *b)
{
    if (*(long long *)a > *(long long *)b) return 1;
    if (*(long long *)b < *(long long *)b) return -1;
    return 0;
}

int main()
{
    long long n = 0, k = 0;
    scanf("%lld%lld",&n,&k); // get n and k, as in your code

    // allocate arrays: k elements for karr, and (n - k) for results in narr
    long long *karr = malloc(sizeof(long long) * k);
    long long *narr = malloc(sizeof(long long) * (n - k));

    // read numbers to skip into karr
    for (int i = 0; i < k; i++) {
        scanf("%lld", &karr[i]);
    }
    // sort karr ascending
    qsort(karr,k,sizeof(long long),llcompare);

    // using pointers to move through narr and karr
    long long *pn = narr; // element of narr to set
    long long *pk = karr; // element of karr to compare against

    // pkend marks the end of karr, to check when we've passed the last omitted
    // number
    long long *pkend = karr + k;

    // loop over the needed range
    for (long long i = 1; i <= n; i++) {
        if (pk != pkend && i == *pk) {
            // if i is the next number to omit, move pk to the next omitted
            // number (without adding i to results)
            pk++;
        } else {
            // otherwise, add i to results then move pn to the next element
            *(pn++) = i;
        }
    }

    // print results from narr
    for (long long i = 0; i < (n - k); i++)
        printf("%lld ", narr[i]);
    printf("\n");

    // free karr and narr when done
    free(karr);
    free(narr);

  return 0;
}

不需要庞大的查找表,并且因为添加到结果中的数字只会增加,所以要跳过的下一个数字将始终是karr中没有数字的最低数字。已经到达...所以只需要为每个新号码检查karr中的一个元素。

上面的代码还假设karr中没有数字未在循环中检查,即karr中没有数字超出范围1..N。并且由于缺少错误检查/处理,如果您输入无效输入或malloc()由于某种原因失败,则可能表现不佳。