Java 查找内存有限的重复元素
以下是一个来自编码面试的问题: 你有一个数组,所有的数字从1到N,其中N最多 32,000. 数组可能有重复的条目,您不知道是什么Java 查找内存有限的重复元素,java,arrays,memory,scalability,Java,Arrays,Memory,Scalability,以下是一个来自编码面试的问题: 你有一个数组,所有的数字从1到N,其中N最多 32,000. 数组可能有重复的条目,您不知道是什么 N是。只有4KB的内存可用,如何打印所有 数组中有重复的元素吗 方法签名是 public static void checkDuplicates(int[] array) 然后,该解决方案解释了如何使用位向量通过将每个整数表示为位来解决此问题。我的困惑是,当我们运行这个方法时,它不会加载内存中的整个数组来循环它吗?现在如果数组的大小,比如说,10亿(许多重复的元素
N是。只有4KB的内存可用,如何打印所有 数组中有重复的元素吗 方法签名是
public static void checkDuplicates(int[] array)
然后,该解决方案解释了如何使用位向量通过将每个整数表示为位来解决此问题。我的困惑是,当我们运行这个方法时,它不会加载内存中的整个数组来循环它吗?现在如果
数组
的大小,比如说,10亿(许多重复的元素)这个程序不会失败,因为它将整个数组加载到内存中,而我们拥有的内存是32*2^10
位?这可能是一个棘手的问题。我最近在谷歌接受了采访,他们提出了一些类似于你的问题。我认为在这些情况下,最好解释一下你的思路并涵盖每一个案例。这些问题也是由人类提出的,因此他们可能漏掉了一个单词等。如果我必须回答这个问题,我会给出多个答案:
- 所有内存使用量可能为4KB(问题等)
- 您的解决方案应适合4KB(上述解决方案)
只有4KB内存可用[…] 因为Java在中是一种有趣的语言,所以在将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可用于内部处理算法。我认为这种限制只是为了防止“我复制它和…”之类的解决方案。4Ko似乎是函数允许的内存量,而不是整个程序,甚至不是,在这种情况下,将内存内容交换到文件中可能非常有帮助。意思是“4KB用于完成任务”因此,您的代码不会占用更多空间。下面是我脑海中编造的代码,但还没有测试过 基本上,只需将数字的值用作位向量中的索引。 如果已经设置,打印消息;否则设置它
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);
}
}
公共类BitVectorMagic{
静态公共无效检查重复项(最终int[]pArray){
最终整数needBytes=(pArray.length/8)+1;
最终字节[]位向量=新字节[neededBytes];
对于(int i=0;i0){
系统输出打印项次(“位置+i处的重复值”+值+);
}否则{
最终字节writeBitByte=setBit(位字节,索引字节);
位向量[byteIndex]=可写字节;
}
}
}
专用静态字节setBit(最终字节pBitByte,最终整数pIndexInByte){
最终字节or=(字节)(0x01>pIndexInByte)&1);
}
}
问题的想法是32000(可能值)/8(字节位)=4000~4096(4KB)
初始阵列内存不计数,因为它的大小没有合理的限制,因为没有给定复制数的限制
4kb
是该方法可以使用的内存量,由于该方法接收到指向输入数组的指针(无需复制其值),因此不计算数组大小
据我所知,任何
O(N)
内存估算都会占用额外的内存,算法可以用来解决这个问题。下面是一个经过测试的代码:
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;
}
}
}
public void checkDuplicates(int[]nums){
int字节数=(nums.length/8)+1;
字节[]位集=新字节[需要字节];
对于(int i=0;我认为这个问题要求在数组已经使用的数据之外再增加4KB。虽然我会说没有时间限制,但即使在恒定的空间中,您也应该能够做到这一点,因为您可以重复循环数组,使用O(32k*n)时间从1到32k计算每个数字。但是问题表明“只有4KB的内存可用"!!我同意它可以在恒定空间中解决,但对于给定的问题陈述,只有当数组大小为2时,解决方案才有效^10@tobias_k我同意tobias的观点。由于只有4KB的可用内存,您如何打印阵列中的所有重复元素?感觉它是指允许您打印重复元素的内存量ates的容量仅为4KB。