如何计算在给定范围内不存在的数字

时间:2013-09-07 17:48:28

标签: c algorithm

我必须打印1到n之间的数字,这些数字在给定的子集中不存在。所有子集都将介于1和n之间。子集始终按升序排列。 例如n = 300并且用户给出的子集是(30到70)(50到100)(150到200)和(250到300)然后我需要打印输出为:数字从1到29,101到149,201至249。

我的方法是:

  1. 将每个数字从1到n并验证它是否存在于任何给定的子集中
  2. 如果在任何给定的子集中不存在,则打印该号码。
  3. 继续。
  4. 我的问题是:

    1. 还有比这更优雅的方法吗?
    2. 我们如何用C语言实现这一点。 (我不是要求逐行代码。我只是想知道我们如何用C语言表示子集以及如何在子集中搜索缺少的数字。)

4 个答案:

答案 0 :(得分:2)

如果n是固定的,即用户不输入,但可以硬编码,则可以定义如下数组:

#define N 300
int my_set[N + 1];

然后用1初始化整个数组,意思是“必须打印这个数字”。 然后,当用户输入子集时,将相应的数组元素设置为0。 最后扫描数组并打印其值仍为1的元素的索引。

答案 1 :(得分:1)

一种方法是(只是给出伪代码):

  1. 按对象中第一个元素的升序对集合进行排序。(已根据您的情况对其进行排序)

  2. 取一个数组并将其中的元素插入:0,p(1,1),p(1,2),p(2,1),p(2,2).... (OP的案例将为0,30,70,50,100,150,200,250,300 ......)

  3. 循环通过数组,同时将计数器(以i为单位)递增2。

  4. if(arr[i]<arr[i+1])arr[i]循环到arr[i+1]并打印元素。否则在将计数器递增2时,转到大于arr[i+1]元素的元素。

  5. 例如:如果数组是:0, 2, 5000, 3, 50, 60, 100, 6000, 6050;从5000开始,递增2,你将跳到6050。

    这种方法的优点在于它不会比较范围内的每个值来打印它,这对于检查要打印或不打印的范围中的每个数字来说是一个巨大的性能繁荣。在C中创建初始数组会有点困难(在c ++中很容易)。

    注意::由于简短的解释,最初可能看起来不清楚和困难但不是。

答案 2 :(得分:0)

这是您可以遵循的方法。 假设你被给予

范围为[1到N],其中N可以是变量(从用户输入)/常量(已经固定)。

子集为Ai [ai,bi],其中1 <= i <= k。即你有k个子集,其中ai是下边界,bi是上边界。

现在开始创建第一个节点为[1,N]的树。在算法执行期间的给定时间,在树中,每个叶节点表示任何给定子集未涵盖的数字范围,即您必须打印数字范围所有叶子节点。

初始条件
从树开始只有一个叶节点[1,N]。因为我们还没有处理任何子集,所以我们必须打印1到N之间的所有数字。

终止条件
在算法结束时,树将包含许多叶子。每个叶子将代表任何子集未涵盖的数字范围。所以你必须打印这些数字作为输出。

<强>算法:

STEP 1: Creating the Tree   
For i = 1 to k  //process for all given subsets
{
    For every leaf node in current tree
    {
        //Let [x,y] is the current leaf node being processed
        1. if(ai>=x && bi<=y) //subset being processed lie inside the leaf being
           processed.
           create nodes [x,ai-x] and [bi+1,y] and attach as child of the leaf node       
           being processed.

        2. if((x<=ai<y) && (bi>y)) //subset overflows towards right
           create a node [x, ai-1] and attach as child to the current leaf node being
           processed.

        3. if((ai<x) && (x<bi<=y)) //subset overflows towards left
           create a node [bi+1, y] and attach as child to the current leaf node being
           processed.
    }
}

STEP 2: Printing the output
//Now the leaf nodes indicate the numbers to be printed.
For each leaf node [x,y] of the resulting tree
{ 
    //you will get some leaf node with x>y
    if(x<=y)
         print the numbers in range [x,y].
} 

答案 3 :(得分:0)

我对C不太了解,但这样的事情呢? n作为第一个命令行参数给出,后跟范围,用空格分隔。

C代码:

#include <stdio.h>

int main(int argc, char** argv) {
    int i, j, count = 1, n, lBound, uBound;

    sscanf (argv[1], "%i", &n);

    for (i = 2; i < argc; i += 2)
    {
        sscanf (argv[i], "%i", &lBound);

        sscanf (argv[i + 1], "%i", &uBound);

        if (lBound > count)
            for (j = count; j <= lBound - 1; j++)
                printf("%d ",j);

        count = uBound + 1;
    }

    if (count < n)
        for (j = count; j <= n; j++)
            printf("%d ",j);
}

输出:

C:\c>notPresent 100 20 80
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 81 82 83 84 85 86 87 88 89 90 91
92 93 94 95 96 97 98 99 100

C:\c>notPresent 100 20 80 60 90
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 91 92 93 94 95 96 97 98 99 100