我最近浏览了一本编码书并遇到了这个有趣的问题。
数组A包含从0到n的所有整数,除了一个数字 失踪。在这个问题中,我们无法通过单个操作访问A中的整个整数。 A的元素以二进制表示,是我们可以使用的唯一操作 访问它们是“获取A [i]的第j位”,这需要恒定的时间。写代码 找到缺少的整数。你能在0(n)时间内完成吗?
本书的作用是通过一个三页的过程来解释如何有效地完成这个问题。说实话,它有点TL; DR对我来说,所以我自己做了解决方案并将它与书的比较。我只是想知道我的解决方案是否真的有效(因为看起来怀疑这本书的答案可以如此长而详细,只需几分钟即可完成更简单的解决方案。)
这是本书的解决方案:
1 public int findMissing(ArrayList<BitInteger> array) {
2 /* Start from the least significant bit, and work our way up */
3 return findMissing(array, 0);
4 }
5
6 public int findMissing(ArrayList<BitInteger> input, int column) {
7 if (column >= BitInteger.INTEGER_SIZE) { // We're done!
8 return 0;
9 }
10 ArrayList<BitInteger> oneBits =
11 new ArrayList<BitInteger>(input.size()/2);
12 ArrayList<BitInteger> zeroBits =
13 new ArrayList<BitInteger>(input.size()/2);
14
15 for (BitInteger t : input) {
16 if (t.fetch(column) == 0) {
17 zeroBits.add(t);
18 } else {
19 oneBits.add(t);
20 }
21 }
22 if (zeroBits. size() <= oneBits.size()) {
23 int v = findMissing(zeroBits, column + 1);
24 return (v « 1) | 0;
25 } else {
26 int v = findMissing(oneBits, column + 1);
27 return (v « 1) | 1;
28 }
29 }
我自己的解决方案对我来说似乎是相同的O(n)时间复杂度,但是在O(1)空间复杂度的情况下完成,要简单得多。我将“fetch”方法定义为接受两个参数。第一个指定第x位,第二个指定索引号。我假设这个方法是给定的,因为它在问题中被提到(“获取A [i]的第j位”)。基本上,我只是检查最低位是否在1和0之间交替 - 这就是它的全部内容。
int findMissing(int[] arr) {
int lowBit = fetch(0, 0); // fetch the 0th bit of arr[0]
if(lowBit != 0) {
return 0; // obviously, the array is not starting at 0, so 0 must be what is removed
}
int expectedNextBit = 1; // we expect the lowest bit to be 1
for(int x = 1; x < arr.length; x++) {
lowBit = fetch(0, x); // fetch the 0th bit (lowest) of arr[x]
if(lowBit != expectedNextBit) {
return x;
}
expectedNextBit = lowBit ^ 0x1;
}
return arr.length;
}
我的问题是 - 我自己的解决方案有什么问题?我是大二学生本科生,这本书是由博士写的,所以我非常怀疑我的答案实际上可能比他们好。
答案 0 :(得分:1)
您的解决方案错误地假定输入数字已排序。如果您的输入为[0, 2, 1, 3, 5]
,则您的解决方案会错误地报告1
,即使它稍后出现在数组中。
答案 1 :(得分:0)
我自己的解决方案出了什么问题?
您的源代码的第一件事是错误的:
提供的源代码未说明要完成的任务。
没有理由使用特殊情况下的索引Id=6
(还有一个很好的理由不这样做:如果0
会怎样?)。
0 == arr.length
可能仅显示:
findMissing()