以下是Cracking the coding采访中提出的一个问题:
你有一个数组从1到N的所有数字,其中N最多 32,000。该数组可能有重复的条目,你不知道是什么 N是。只有4KB的可用内存,您将如何打印所有内存 数组中的重复元素?
方法签名是
SELECT t.*
FROM t
WHERE t.col2 IN (5, 7, 9) AND
t.col1 IN (SELECT col1
FROM t
WHERE col1 > 1645 AND col2 IN (5, 7, 9)
GROUP BY col1
HAVING COUNT(DISTINCT col2) = 3
);
然后解决方案解释了如何使用位向量来解决这个问题,方法是将每个整数表示为一个位。我的困惑是当我们运行这个方法时,它不会将整个数组加载到内存中以循环它吗?现在,如果public static void checkDuplicates(int[] array)
的大小有,例如,10亿(许多重复的元素)将不会失败,因为它将整个数组加载到内存中,而我们的内存是array
位?
答案 0 :(得分:4)
这可能是一个棘手的问题。我最近在谷歌接受了采访,他们遇到了类似你的问题。我认为最好在这些情况下解释你的思路并涵盖每个案例。这些问题也是由人类构建的,所以他们可能错过了一个单词等。如果我不得不回答这个问题,我会想出多个答案:
案文说:
只有4KB的可用内存[...]
因为Java是terms of passing values中一种有趣的语言,所以在传递给方法时,不会创建int数组的新实例。
public class Test {
public static void main(String[] args) {
int[] stuff = {1};
System.out.println("before: " + stuff[0]);
doStuff(stuff);
System.out.println("after: " + stuff[0]);
}
public static void doStuff(int[] array){
array[0]=10;
}
}
由于这种行为,您的4KB可用于内部处理算法。我认为这种限制只是为了防止“我复制它和......”的解决方案。
答案 1 :(得分:4)
以下是经过测试的代码:
public void checkDuplicates(int[] nums){
int bytesNeeded = (nums.length/8) + 1;
byte[] bitSet = new byte[bytesNeeded];
for(int i=0; i<nums.length; i++){
int n = nums[i];
int byteIndex = n / 8;
int indexInByte = n % 8;
byte bit = (byte)(bitSet[byteIndex] & (1 << indexInByte));
if(bit > 0){
System.out.print(nums[i] + " ");
}else{
bitSet[byteIndex] |= 1 << indexInByte;
}
}
}
答案 2 :(得分:0)
4Ko似乎是函数的允许内存量而不是整个程序,甚至没有,在这种情况下将内存内容交换到文件中会非常有用{。{3}}。
答案 3 :(得分:0)
完成任务的平均值&#34; 4KB&#34;所以你的代码并不意味着占用更多的空间。这里的代码在我的脑海中被编写但尚未经过测试。
基本上只需使用数字的值作为位向量中的索引。 如果已经设置,则打印消息;否则设置它。
public class BitVectorMagic {
static public void checkDuplicates(final int[] pArray) {
final int neededBytes = (pArray.length / 8) + 1;
final byte[] bitVector = new byte[neededBytes];
for (int i = 0; i < pArray.length; i++) {
final int value = pArray[i];
final int byteIndex = value / 8;
final int indexInByte = value % 8;
final byte bitByte = bitVector[byteIndex];
final byte bit = getBit(bitByte, indexInByte);
if (bit > 0) {
System.out.println("Duplicate value " + value + " at pos " + i);
} else {
final byte writeBitByte = setBit(bitByte, indexInByte);
bitVector[byteIndex] = writeBitByte;
}
}
}
private static byte setBit(final byte pBitByte, final int pIndexInByte) {
final byte or = (byte) (0x01 << pIndexInByte);
return (byte) (pBitByte | or);
}
static private byte getBit(final int pByte, final int pIndexInByte) {
return (byte) ((pByte >> pIndexInByte) & 1);
}
}
答案 4 :(得分:0)
问题的想法是32000 (possible values) / 8 (bit in byte) = 4000 ~ 4096 (4 KB)
。
初始数组内存不计算,因为它的大小没有合理的限制,因为没有给出重复数量的限制。
4 KB
是方法可以使用的内存量,并且由于该方法接收到指向输入数组的指针(不需要复制其值),因此不会计算数组大小。
据我所知,任何O(N)
内存估计都会考虑额外的内存算法可以用来解决问题。