【问题标题】:Finding duplicate elements with limited memory查找内存有限的重复元素
【发布时间】:2016-11-28 02:59:57
【问题描述】:

以下是Cracking the coding interview的一个问题:

你有一个包含从 1 到 N 的所有数字的数组,其中 N 最多 32,000。数组可能有重复的条目,你不知道是什么 N是。只有 4KB 可用内存,您将如何打印所有 数组中有重复元素?

方法签名是

public static void checkDuplicates(int[] array)

然后解决方案解释了如何使用位向量通过将每个整数表示为位来解决此问题。我的困惑是当我们运行这个方法时,它不会将整个数组加载到内存中循环遍历它吗?现在如果array 的大小例如,10 亿(许多重复元素),这个程序不会失败,因为它将整个数组加载到内存中,而我们拥有的内存是32 * 2^10 位?

【问题讨论】:

  • 我认为问题需要 4KB additional 到阵列已经使用的内容。虽然我会说没有时间限制,但即使在恒定空间中你也应该能够做到这一点,因为你可以重复循环数组并使用 O(32k*n) 时间从 1 到 32k 计数每个数字。跨度>
  • 但问题是“只有 4KB 可用内存”!!我同意它可以在恒定空间中解决,但是对于给定的问题陈述,该解决方案仅在数组大小为 2^10 时才有效
  • @tobias_k 我同意 tobias。
  • 只有 4KB 可用内存,如何打印数组中的所有重复元素?感觉它是指您允许消耗的内存量来打印副本,它几乎是 4KB。

标签: java arrays memory scalability


【解决方案1】:

下面是经过测试的代码:

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】:

    这可能是一个棘手的问题。我最近在谷歌面试,他们有一些像你这样的问题。我认为在这些情况下最好解释您的思路并涵盖每种情况。这些问题也是由人类构建的,所以他们可能漏掉了一个词等。如果我必须回答这个问题,我会想出多个答案:

    • 所有内存使用量可能为 4KB(问题等)
    • 您的解决方案应该适合 4KB(提到的解决方案)

    文字说:

    只有 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 可用于您的内部处理算法。我认为这个限制只是为了防止“我复制它然后……”之类的解决方案。

    【讨论】:

      【解决方案3】:

      4Ko 似乎是函数允许的内存量而不是整个程序,甚至不是,在这种情况下将内存内容交换到文件中可能非常有用look here

      【讨论】:

        【解决方案4】:

        意思是“完成任务需要 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);
            }
        }
        

        【讨论】:

          【解决方案5】:

          问题的意思是32000 (possible values) / 8 (bit in byte) = 4000 ~ 4096 (4 KB)

          初始数组内存不计算在内,因为它的大小没有合理的限制,因为没有给出重复次数的限制。

          4 KB 是该方法可以使用的内存量,并且由于该方法接收指向输入数组的指针(无需复制其值),因此不计算数组大小。

          据我所知,任何O(N) 内存估计占额外内存的算法都可以用来解决问题。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2022-01-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多