Topic 5.7 An array A contains all the integers from 0 to n except for one number which is missing. In this problem, we cannot access an entire integer in A with a single operation. The elements of A are represented in binary, and the only operation we can use to access them is “fetch the jth bit of A[i]”, which takes constant time. Write code to find the missing integer. Can you do it in O(n) time?
引申问题1:Given a list of numbers from 0 to n, with one number removed, find the missing number.
è Sum all numbers, compare it to the sume of 0 through n【n*(n-1)/2】. The difference is the missing number.
方法1: Computing the value of each number, based on its binary representation, and calculate the sum. Time: O(nlog(n))----n*length(n), length is the number of bits in n. length(n)=log2(n).
方法2: Removing a number creates an imbalance of 1s and 0s in the least significant bit, LSB1.
1) If n is odd, count(0s)=count(1s); If n is even, count(0s)=1+count(1s)
2) If n is odd & the removed number is odd, count(0s)>count(1s);
If n is odd & the removed number is even, count(0s)<count(1s);
If n is even & the removed number is odd, count(0s)>count(1s);
If n is even & the removed number is even, count(0s)=count(1s);
->Discard the unsatisfied n/2 numbers.
3) Repaet and count LSB2, ..LSBn, we look at n, then n/2, then n/4 and so on. Time: O(n).
public class BitInteger {
public static int INTEGER_SIZE;
private boolean[] bits;
public BitInteger() {
bits = new boolean[INTEGER_SIZE];
}
/* Creates a number equal to given value. Takes time proportional
* to INTEGER_SIZE. */
public BitInteger(int value){
bits = new boolean[INTEGER_SIZE];
for (int j = 0; j < INTEGER_SIZE; j++){
if (((value >> j) & 1) == 1) bits[INTEGER_SIZE - 1 - j] = true;
else bits[INTEGER_SIZE - 1 - j] = false;
}
}
/** Returns k-th most-significant bit. */
public int fetch(int k){
if (bits[k]) return 1;
else return 0;
}
/** Sets k-th most-significant bit. */
public void set(int k, int bitValue){
if (bitValue == 0 ) bits[k] = false;
else bits[k] = true;
}
/** Sets k-th most-significant bit. */
public void set(int k, char bitValue){
if (bitValue == '0' ) bits[k] = false;
else bits[k] = true;
}
/** Sets k-th most-significant bit. */
public void set(int k, boolean bitValue){
bits[k] = bitValue;
}
public void swapValues(BitInteger number) {
for (int i = 0; i < INTEGER_SIZE; i++) {
int temp = number.fetch(i);
number.set(i, this.fetch(i));
this.set(i, temp);
}
}
public int toInt() {
int number = 0;
for (int j = INTEGER_SIZE - 1; j >= 0; j--){
number = number | fetch(j);
if (j > 0) {
number = number << 1;
}
}
return number;
}
}
import java.util.ArrayList;
public class c5_8 {
public static ArrayList<BitInteger> initialize(int n, int missing) {
BitInteger.INTEGER_SIZE = Integer.toBinaryString(n).length();
ArrayList<BitInteger> array = new ArrayList<BitInteger>();
for (int i = 1; i <= n; i++) {
array.add(new BitInteger(i == missing ? 0 : i));
}
return array;
}
public static int findMissing(ArrayList<BitInteger> array) {
return findMissing(array, BitInteger.INTEGER_SIZE - 1);
}
private static int findMissing(ArrayList<BitInteger> array, int column) {//从最高位开始堆栈,打印是从最高位开始的
if (column < 0) { // Base case and error condition
return 0;
}
ArrayList<BitInteger> oneBits = new ArrayList<BitInteger>(array.size()/2);//它是一个存了尾数是1的数的数组
ArrayList<BitInteger> zeroBits = new ArrayList<BitInteger>(array.size()/2);//它是一个存了尾数是0的数的数组
for (BitInteger a : array) {
if (a.fetch(column) == 0) {//fetch的是当前位,仅一位
zeroBits.add(a);
} else {
oneBits.add(a);
}
}
if (zeroBits.size() <= oneBits.size()) {//说明缺0
int v = findMissing(zeroBits, column - 1);
return (v<<1)|0;//左移一位,跟0或,让最右边是0
}else {
int v = findMissing(oneBits, column - 1);//说明缺1
return (v<<1)|1;//左移一位,跟1或,让最右边是1
}
}
public static void main(String[] args) {
int n = 35;
int missing = 14;
ArrayList<BitInteger> array = initialize(n, missing);
System.out.println("The array contains all numbers but one from 0 to " + n);
System.out.println("The missing number is: "+findMissing(array));
}
}
//结果
The array contains all numbers but one from 0 to 35
The missing number is: 14