找出所缺的整数

某数组A[1...n]含有所有从0到n的整数,但其中有一个整数不在数组中。通过利用一个辅助数组B[0...n]来记录A中出现的整数,很容易在O(n)时间内找出所缺的整数。但如果A中的元素是以二进制表示的,我们所能用的唯一的操作就是取A[i]的第j位。


第一种以十进制的代码,是利用一个辅助数组来进行计数,然后扫描辅助数组,从而来确定所缺少的数字:

#include<iostream>
using namespace std;


int main()
{
    cout << "Please enter the range of the numbers:";
    int range;                  //输入数字范围
    cin >> range;
    int *A = new int [range];   //建立输入数组
    int *B = new int [range + 1];//建立辅助数组
    for(int i = 0;i <= range;i++){
        B[i] = 0;
    }
    int i = 0;
    int temp;
    cout << "Please enter the number you have:";
    while(cin >> temp && i < range){
        A[i] = temp;
        i++;
    }
    int j = 0;
    while(j < i){
        B[A[j]]++;
        j++;
    }
    for(i = 0;i <= range;i++){
        if(B[i] == 0)
            cout << i << " ";
    }
    cout << endl;
    return 0;
}
        B[A[j]]++;
        j++;
    }
    for(i = 0;i <= range;i++){
        if(B[i] == 0)
            cout << i << " ";
    }
    cout << endl;
    return 0;
}

关于二进制的,我只做到了时间复杂度是O(nlgn),而书上却说能做到O(n)的时间复杂度。。。

首先存储模式,我用的是二维数组。通过二进制数的性质我们可以知道,二进制数的长度为(lgn) + 1(计算机中lg我默认以2为低)。为了计算方便,我将所有的数的二进制全部都扩容成(lgn) + 1的长度,这样,二维数组消耗总的存储空间为nlgn。

接下来,可以利用将二进制数转化为十进制数的思想。我们知道,将2进制数转化为十进制数的方法为:

以右端为起始位,记为n = 1,该位上的数字i(i=0或1),共计有m位,将十进制数记为d,则d=∑(n = 1在下,m在上)i * 2 ^ ( n - 1 )【数学公式写不好。。。求各位看官海涵】

我们将二位数组每一列上的数字相加,得到该列的和,并存储。依次进行(lgn) + 1次,然后根据上面的公式,利用牛顿多项式求和方法,来减少乘法的运算次数。得出和。

而通过计算,我们可以知道完整的序列求和的结果。因此,想减后,得到了缺少的一个数字。

注意,这个方法的局限性在于,只能缺少一个数字的情况下使用,如果多个数字,还是要逐行求出十进制数,然后借助辅助数组进行筛选,与上方代码的方法类似,只是多了一个将二进制数转化为十进制数的步骤。

二进制寻找:

#include<iostream>
#include<cmath>
using namespace std;

void bin(int **A,int i,int row,int col)
{
    while(i != 0)
    {
        A[row][col] = i % 2;
        i /= 2;
        col--;
    }
    return;
}

int main()
{
    cout << "Please enter the range of the numbers:";
    int range;                  //输入数字范围
    cin >> range;
    int col = log(range) / log(2) + 1;
    int **A = new int * [range + 1];   //建立输入数组
    for(int i = 0;i <= range;i++){
        A[i] = new A[col];
    }
    for(int i = 0;i <= range;i++){
        for(int j = 0;j < col;j++)
            A[i][j] = 0;
    }
    int i = 0;
    int temp;
    cout << "Please enter the number you have:";
    while(cin >> temp && i < range){
        bin(A,temp,i,col);
        i++;
    }
    for(i = 0;i < col;i++)
        for(int j = 0;j < range;j++)
            A[range][i] += A[j][i];
    int result1 = A[range][0];
    for(i = 0;i < col - 1;i--){
        result1 = 2 * result1 + A[range][i+1];
    }
    int result2 = 0;
    for(i = 0;i <= range;i++)
        result2 += i;
    int target = result2 - result1;
    cout << "所缺的数是:" << target << endl;
    cout << endl;
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值