有效地创建一个包含 n 个数字的数组,不包括 k 个给定数字
Creating an array of n numbers excluding k given numbers efficiently
如何创建一个从 1 开始到 n 结束的数字数组,同时不包括数组中的 k 个给定数字?例如 n=10 k=2 并且 k 值的两个数字是 3 和 6 那么我的数组是 1,2,4,5,7,8,9,10.
我必须对大量数据执行此操作,例如
1 < n < 10^9
然后
0 < k < min(10^5,n)
对于小数字,我尝试建立索引,然后将其存储在另一个数组中,这占用了很多 space 和 time.How 我可以有效地做到这一点吗?
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;
}
}
使用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;
}
不需要大量查找 table,并且由于添加到结果中的数字只会增加,下一个要跳过的数字将始终是 karr
中没有的最小数字' t 已经达到...所以只需要为每个新数字检查 karr
中的一个元素。
上面的代码还假设karr
中没有数字在循环中不会被检查,即karr
中没有数字超出范围1..n.并且由于缺少错误 checking/handling,如果您给它无效输入或 malloc()
由于某种原因失败,它可能会表现得很糟糕。
如何创建一个从 1 开始到 n 结束的数字数组,同时不包括数组中的 k 个给定数字?例如 n=10 k=2 并且 k 值的两个数字是 3 和 6 那么我的数组是 1,2,4,5,7,8,9,10.
我必须对大量数据执行此操作,例如
1 < n < 10^9
然后
0 < k < min(10^5,n)
对于小数字,我尝试建立索引,然后将其存储在另一个数组中,这占用了很多 space 和 time.How 我可以有效地做到这一点吗?
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;
}
}
使用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;
}
不需要大量查找 table,并且由于添加到结果中的数字只会增加,下一个要跳过的数字将始终是 karr
中没有的最小数字' t 已经达到...所以只需要为每个新数字检查 karr
中的一个元素。
上面的代码还假设karr
中没有数字在循环中不会被检查,即karr
中没有数字超出范围1..n.并且由于缺少错误 checking/handling,如果您给它无效输入或 malloc()
由于某种原因失败,它可能会表现得很糟糕。