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

前言

大部分算法默认给定的数据量都比较小,只有几个或者几十个元素,但是如果将数据量提高到百万甚至几十亿,那么处理逻辑就会发生很大差异。在海量数据中,普通数据结构都无效了,因为内存空间放不下,常规的递归、排序、回溯、贪心和动态规划等思想也无效了,执行都会超时。这里介绍三种非常典型的思路:

  1. 使用位存储,其最大的好处是占用的空间是直接存储整数的 1 8 \frac{1}{8} 81,例如一个40亿的整数数组,如果用整数存储需要16GB左右的空间,而如果使用位存储,就可以用大约0.5GB的空间,大大节省了存储空间。
  2. 如果文件实在太大,无法在内存中放下,就需要考虑将大文件分成若干小块,先处理每个块,最后再逐步得到想要的结果,这种方式也叫做外部排序。这样需要遍历全部序列至少两次,是典型的用时间换空间的方法。
  3. 用堆,如果在超大数据中找第K大、第K小,K个最大、K个最小,则特别适合使用堆来做。而且超大数据换成流数据也可以,而且几乎是唯一的方式,口诀就是“查小用大堆,查大用小堆”。

用4KB内存寻找重复元素

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

分析:首先计算所需的位向量大小,然后创建一个位向量数组,将数组中的元素映射到位向量中的位。在遍历数组时,它检查位向量中的相应位是否已经设置,如果已设置,则表示重复元素,将其添加到结果数组中。如果未设置,则将相应位设置为1,表示已经访问过该元素。最后,返回包含重复元素的数组。

代码如下:

function findDuplicates(arr) {
    // 根据最大可能的N值,计算所需的位向量大小(bit数组大小)
    const maxN = 32000;
    const vectorSize = Math.ceil(maxN / 32);

    // 初始化位向量,每个元素都为0
    const bitVector = new Array(vectorSize).fill(0);

    // 用于存储重复元素的数组
    const duplicates = [];

    for (const num of arr) {
        const index = Math.floor((num - 1) / 32); // 计算位向量中的索引
        const bit = 1 << ((num - 1) % 32); // 计算在索引中的位

        // 如果该位已经被设置为1,说明该元素是重复的
        if ((bitVector[index] & bit) !== 0) {
            duplicates.push(num);
        } else {
            // 否则,将该位设置为1,表示已经访问过该元素
            bitVector[index] |= bit;
        }
    }

    return duplicates;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值