报告整数数组中的所有缺失数字(以二进制表示)

时间:2011-03-21 06:36:30

标签: algorithm

我最近有一位朋友向我汇报,在求职面试时他被问到以下问题,这个问题似乎很受欢迎:

您将获得一个列表L[1...n],其中包含从0到n的所有元素,除了一个。此列表的元素以二进制and are not given in any particular order表示,我们可以用来访问它们的唯一操作是在常量时间内获取L [i]的第j位。 如何找到O(n)中缺少的号码?

他能够回答这个问题(我相信有多个解决方案,其中没有一个太复杂)。例如,以下伪代码解决了上述问题:

Say all numbers are represented by k bits and set j as the least significant bit (initially the rightmost).
1. Starting from j, separate all the numbers in L into two sets (S1 containing all numbers that have 1 as its jth bit, and S2 containing all numbers that have 0 in that position).
2. The smaller of the two sets contains the missing number, recurse on this subset and set j = j-1

在每次迭代中,我们将集合的大小减半。所以最初我们有O(n),然后是O(n / 2),O(n / 4)...... = O(n)

然而,后续问题是:"如果我们现在列表L中缺少 k 号码,我们希望报告所有 k 号码仍然保持O(n)复杂性和初始问题的局限性?怎么做?

有什么建议吗?

3 个答案:

答案 0 :(得分:1)

bool J[1..n + 1]={false,false...}
int temp;

for(i = 1; i <= n; i++)
{
    temp=bitwisecopy of L[i];
    J[temp + 1]=true
}

for(i = 1; i <= n+1; i++)
{
    if(J[i]==false)
       print i + 1;
}

Lol认为它的主旨......我认为指数可能搞砸了。

我是否正确理解了问题?我并不是很清楚,唯一的操作是什么意思才能访问L [i]的第j位。

答案 1 :(得分:0)

你可以通过对数组执行线性遍历来解决O(n)中的原始问题,直到找到与预期值不匹配的数字,就像这样(是的,我知道我正在使用数组ints近似比特数组,但概念是相同的):

int[] bits = {1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0};
int bitIndex = 0;
for (int num = 1; num < Integer.MAX_VALUE; num++) {
    int numBits = (int) (Math.log(num) / Math.log(2)) + 1;
    int nextNum = 0;
    for (int index = 0; index < numBits; index++) {
        nextNum = (nextNum << 1) | bits[bitIndex + index]; 
    }
    if (nextNum != num) {
        System.out.println("Missing number:  expected=" + num + ", actual=" + nextNum);
        break;
    }

    bitIndex += numBits;
}

如果要在保持O(n)运行时的同时打印阵列中不存在的所有数字,只需将break;替换为num = nextNum;即可继续检查下一个数字。< / p>

虽然这种方法存在一些潜在的问题。如果缺少多个连续号码,则所有投注均已关闭。此外,如果num + 1中的位数大于num中的位数,并且位数组中缺少num,则位索引将与...不一致数据

当然,如果允许丢失多个号码,那么问题就无法解决。考虑例如:

{1,1,1,1,1,1,1}

在这种情况下同样有效的是说我有数字1,3和15,因为它说我只有127或者我有7和15.当允许多个连续值丢失时,解析位的方法基本上变得随意。

所以也许回答第二个问题的一种方法是将所有位读成一个大整数,并说“你有[非常大的数字],并且它之前的所有数字都丢失了”。然后你在O(n)时间内产生了一个有效的答案。

答案 2 :(得分:0)

我的想法是通过以下方式解决它:

假设2 ^ M是2的最低幂,高于N:

2^M>N,    2^M-1 <= N

现在查看从1到2 ^ M-1的所有数字,并在所有数字之间进行按位异或 (因为你每次只能分别对每个数字进行比特来检查它 - 它是相同的)

所有XOR的结果将是您要查找的数字。

例如:如果N = 6,则缺少的数字是3:

M=3 => 2^M-1=7 =>
1 XOR 2 XOR 4 XOR 5 XOR 6 XOR 7 = 3