• 算法通关村第十五关:青铜-用4KB内存寻找重复元素


    青铜挑战-用4KB内存寻找重复元素

    位运算在查找元素中的妙用

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

    思路分析

    本题是非常典型的海量数据处理的问题,使用的是位运算结构

    内存大小关系
    1字节 = 1byte(拜特) = 1B = 8bit(比特,位)
    1KB = 1024B
    1MB = 1024KB
    1GB = 1024MB

    如果没有内存要求,创建一个大小为N的数组,然后将这些整数(32位)放进来,N最大为32000,则需要 320004B ≈ 128KB
    如果只有4KB的空间,那么只能寻址 4KB = 4*1024B = 4*1024
    8bit(比特) 该值大于32000
    因此我们可以创建32000比特的位向量(比特数组),其中一个比特位置就代表一个整数,类似索引

    利用这个位向量,就可以遍历访问整个数组。如果发现数组元素是v,那么就将位置为v的位设置为1,碰到重复元素,就输出一下

    代码实现

    1个数组元素存储 32 个数字信息,如索引为0的元素存储1~32

    def check_duplicates(array):
        bitset = [0] * (32000 // 32)
        for num in array:
            num0 = num - 1
            if (bitset[num // 32] >> (num0 % 32)) & 1:
                print(num)
            else:
                bitset[num // 32] |= (1 << (num0 % 32))
    
    
    if __name__ == '__main__':
        check_duplicates([1, 2, 3, 2])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    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);
                }
            }
    
        }
    
        static 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;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
  • 相关阅读:
    【JAVASE系列】09_toString和equals和内部类
    深度学习归一化原理及代码实现(BatchNorm2d,LayerNorm,InstanceNorm,GroupNorm)
    豪越智慧后勤管理平台为企业带来哪些转变?
    【分享一个实用帖,带视频】教你用RPA高效进行软件测试
    全面解读 AWS Private 5G 的革新理念
    【RocketMQ】主从同步实现原理
    2023-2028年中国硫氰酸胍(GTC)市场研究及前景投资预测报告
    2024年浙大MBA项目必报名的三个理由
    【C++】哈希表
    JAVA并发编程——线程池详解
  • 原文地址:https://blog.csdn.net/qq_41662142/article/details/132692010