数据结构面试题之位图查找

1.思路有的人一看到这个题,很简单嘛最麻烦的就是从头遍历一遍的事情嘛. 不过要看清楚题! 40亿个无符号整数.我们生活中1G内存占用的字节数1024*1024*1024为10

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

题目: 给40个亿不重复的无符号整数,没有排序过,随机给出一个无符号整数,快速的判断这个数在或者不在40亿个数中?

1. 思路 

  有的人一看到这个题,很简单嘛最麻烦的就是从头遍历一遍的事情嘛. 不过要看清楚题! 40亿个无符号整数.  我们生活中1G内存占用的字节数1024*1024*1024为1073741824个字节.粗略就是10亿个字节. 而40亿个无符号整数是160亿个字节. 也就是这些数据存储下来需要16G的内存. 那么问题来了,普通的工作电脑的内存都4G,好点的就是8G. (如果你是16G内存光速吃鸡那么当我没说)我们可以发现这些数据的内存大于电脑的内存所以存储不下. 这个时候就很头大了,内存都存不下那么你怎么读取呢? 当然你说你直接去硬盘里面读.好! 没问题.从硬盘里面读取数据的速度和从内存中读取的速度根本没得比的.如果你的时间多也可以.不过我们有一个更厉害的方法就是我们的位图.位图就是给定一段连续的空间然后让这个空间的每一位都为0,再然后让每一个位表示一个数字.再然后当你这个数字出现的 时候将它对应的那个位->置为1.这样的话存储40亿个数据,也就是存储40亿个位.也就是5亿个字节.大概512MB的样子. 这样的话我们的内存存储这些数据也就是绰绰有余了.所以位图对于大数据的问题有着显著的效果。

2. 代码实现

#include "stdio.h"

// 用位图的方式实现大数据的查找
#include <vector>
#include <iostream>
using namespace std;

class CBitmapFind
{
    enum{INFOBITS_IN_VECT = 8};
public:
    // 确定容器大小
    explicit CBitmapFind(size_t nRange = 0)
    {
        BitmapVect.resize(nRange / INFOBITS_IN_VECT + 1);
    }
    // 添加单个元素并标记该元素
    void AddElement(int nNum)
    {
        // 确定该数据所在vect中的位置
        int nVectIndex = nNum / INFOBITS_IN_VECT;
        // 确定在vect索引中的byte位置
        int nByteIndex = nNum % 8;
        
        BitmapVect[nVectIndex] |= (1 << nByteIndex);
    }
    // 删除单个元素并移除单个元素
    void MoveElement(int nNum)
    {
        // 确定该数据所在vect中的位置
        int nVectIndex = nNum / INFOBITS_IN_VECT;
        // 确定在vect索引中的byte位置
        int nByteIndex = nNum % 8;
        
        BitmapVect[nVectIndex] &= ~(1 << nByteIndex);
    }

    bool TestBit(int nNum)
    {
        // 确定该数据所在vect中的位置
        int nVectIndex = nNum / INFOBITS_IN_VECT;
        // 确定在vect索引中的byte位置
        int nByteIndex = nNum % 8;

        return (BitmapVect[nVectIndex] & (1 << nByteIndex)? true:false);
    }
private:
    vector<char> BitmapVect;
};

3. 扩展:判断出现是次数是否大于3

// 用位图的方式实现大数据的查找,判断出现的次数,下面的代码只能处理出现次数小于等于3的情况
// 00 01 10 11
class CNBitmapFind
{
public:
    enum{ INFOBITS_IN_VECT = 4 };
    // 确定容器大小
    explicit CNBitmapFind(size_t nRange = 0)
    {
        BitmapVect.resize(nRange / INFOBITS_IN_VECT + 1);
    }
    // 添加单个元素并标记该元素出现的次数
    void AddElement(int nNum)
    {
        // 确定该数据所在vect中的位置
        int nVectIndex = nNum / INFOBITS_IN_VECT;
        // 确定元素在vect索引中的byte位置
        int nByteIndex = nNum % INFOBITS_IN_VECT;
        nByteIndex *= 2;

        bool first = BitmapVect[nVectIndex] & (1 << nByteIndex);
        bool second = BitmapVect[nVectIndex] & (1 << (nByteIndex + 1));

        if (!(first && second))
        {
            BitmapVect[nVectIndex] += (1 << nByteIndex);
        }
    }

    int Test(int nNum)
    {
        // 确定该数据所在vect中的位置
        int nVectIndex = nNum / INFOBITS_IN_VECT;
        // 确定元素在vect索引中的byte位置
        int nByteIndex = nNum % INFOBITS_IN_VECT;

        nByteIndex *= 2;
        int first = BitmapVect[nVectIndex] & (1 << nByteIndex)?1:0;
        int second = BitmapVect[nVectIndex] & (1 << (nByteIndex + 1))?1:0;

        return second * 2 + first;
    }
private:
    vector<char> BitmapVect;
};

4. 测试

void main()
{
    int nReange = 4 * pow(10, 2);
    CBitmapFind BitmapFind(nReange);
    for (int i = 0; i < nReange; i++)
    {
        BitmapFind.AddElement(i);
    }
    cout << "CBitmapFind测试:" << endl;
    BitmapFind.TestBit(401) ? (cout << "找到:" << 401 << endl) : (cout << "未找到" << 401 << endl);
    BitmapFind.TestBit(388) ? (cout << "找到" << 388 << endl) : (cout << "未找到" << 388 << endl);

    CNBitmapFind NBitmapFind(6);
    NBitmapFind.AddElement(1);
    NBitmapFind.AddElement(1);
    NBitmapFind.AddElement(1);
    NBitmapFind.AddElement(2);
    NBitmapFind.AddElement(2);
    NBitmapFind.AddElement(3);

    cout << "CNBitmapFind测试:" << endl;
    cout << "1出现的次数:" << NBitmapFind.Test(1) << endl;
    cout << "2出现的次数:" << NBitmapFind.Test(2) << endl;
    cout << "3出现的次数:" << NBitmapFind.Test(3) << endl;
}

数据结构面试题之位图查找

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120125.html原文链接:https://javaforall.net

(0)
上一篇 2021年12月28日 下午2:00
下一篇 2021年12月28日 下午2:00


相关推荐

  • 离散数学总复习精华版(最全 最简单易懂)已完结

    离散数学总复习精华版(最全 最简单易懂)已完结离散数学期末总复习精华版P1命题逻辑的基本概念虽然是不确定但是可以是命题就是无法判断真假优先级P2命题逻辑等值演算第一种方法:真值表求第二种用等值演算求P3命题逻辑推理理论下面给出例题后面的可以写成前提引入T12下面给出反证法附加前提证明:…………

    2022年6月18日
    29
  • docker加载配置文件重启服务导致pod重启

    docker加载配置文件重启服务导致pod重启

    2021年6月1日
    95
  • 计算机基础知识总结

    计算机基础知识总结01 01 计算机基础知识 计算机概述 A 什么是计算机 计算机在生活中的应用举例计算机 Computer 全称 电子计算机 俗称电脑 是一种能够按照程序运行 自动 高速处理海量数据的现代化智能电子设备 由硬件和软件所组成 没有安装任何软件的计算机称为裸机 常见的形式有台式计算机 笔记本计算机 大型计算机等 应用举例 1 科学计算 2 数据处理 3 自动控制 4 计算机辅助设计 5 人工智

    2026年3月26日
    2
  • Coze平台实战教程:手把手教你从0搭建一个智能体,全部跟下来你就Agent入门了!

    Coze平台实战教程:手把手教你从0搭建一个智能体,全部跟下来你就Agent入门了!

    2026年3月12日
    3
  • 菜鸟教程java的list_Java菜鸟教程

    菜鸟教程java的list_Java菜鸟教程分阶段进阶教学+阶段考评让学习无死角因为考虑学员基础水平参差不齐,所以动力节点的课程安排对学员进行科学细致的划分,整个教学安排共分两大部分即:基础部分和就业部分,基础部分课程由教学总监定制最适合零基础入门的课程大纲;就业部分课程由教研部实地探访名企如百度、京东、新浪等企业,将最前沿的技术引入到课堂,同时又根据就业课程的深度不同划分为7个阶段,每个阶段都有不同的技术侧重点,层层深入。纵观来看,动力…

    2022年6月13日
    31
  • java read dxf xdata_DXF格式文件数据提取

    java read dxf xdata_DXF格式文件数据提取图元信息提取 下面具体介绍该工程中读取的几种图元 对图元信息的提取需要结合 DXF 参考手册以及库文件 主要涉及 dl entities h 和 dl dxf cpp 选取实际所需数据进行自定义图元信息构造 比如说绘制二维平面图形 则不需要 z 轴坐标 此时只需要读取 data 中 x y 值即可 而在绘制 ARC 时 需要考虑到 OCS 到 WCS 的变化 而库文件读取的 data 中没有涉及到拉伸方向的读取 所以此时需要

    2026年3月18日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号