算法通关村——位运算在查找重复元素中的妙用

遇到很多大的数据量只给很少一点内存, 一般来所有下面三种解法:

  1. 使用位运算存储:为运算的优势就是省内存
  2. 使用堆:适用于寻找超大数据中找第K大、第K小,K个最大、K个最小
  3. 如果文件实在太大 ,无法在内存中放下,则需要考虑将大文件分成若干小块,先处理每个块,最后再逐步得到想要的结果。

用4KB内存寻找重复元素

题目要求:给定一个数组,包含从1到N的整数,N最大为32000,数组可能还有重复值,且N的取值不定,若只有4KB的内存可用,该如何打印数组中所有重复元素。

如果我们使用的就是数组,我们所需要的内存最少就要有

public class FindDuplicatesIn32000 {
    public void checkDuplicates(int[] array) {
        BitSet bs = new BitSet(32000);
        for (int i = 0; i < array.length; i++) {
            int num = array[i];
            int num0 = num - 1;
            if (bs.get(num0)) {
                System.out.println(num);
            } else {
                bs.set(num0);
            }
        }
    }
    class BitSet {
        int[] bitset;

        public BitSet(int size) {
            this.bitset = new int[size >> 5];
        }

        boolean get(int pos) {
            int wordNumber = (pos >> 5);//除以32
            int bitNumber = (pos & 0x1F);//除以32
            // 这里就是对应位运算的获取操作,有固定的套路
            return (bitset[wordNumber] & (1 << bitNumber)) != 0;
        }

        void set(int pos) {
            int wordNumber = (pos >> 5); //除以32
            int bitNumber = (pos & 0x1F); //除以32
            // 这里就是对应位运算的设置对应的值
            bitset[wordNumber] |= 1 << bitNumber;
        }
    }
}

下面来解释一下这段代码的原理

首先创建了一个 bit 字节的数组

BitSet bs = new BitSet(32000);

让后遍历传入的数据,我们通过对应的 值 - 1索引找到了对应的 bs 中的位置,找到了位置之后我们干一件事

判断这个位置是 0 还是 1

  • 如果是 0 的话把 bs 的当前位置设置成 1
  • 如果是 1 的话那么打印对应的值就 ok

这样我们就可以使用非常少的内存找到重复的元素,非常的巧妙!

你可能感兴趣的:(算法,算法,数据结构)