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

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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • QQ群无故消失或QQ群无故被解散

    QQ群无故消失或QQ群无故被解散最近遇到一个怪事情,关于QQ群的,我有一个QQ群凭空消失了,没有任何通知,没有任何消息,上群管理也查询不到恢复记录。据说是群内有违规信息被强制删除解散了,实在想不出有啥违规信息的,那是一个技术QQ群!…

    2022年5月20日
    195
  • 物联网网络架构_物联网技术有哪些

    物联网网络架构_物联网技术有哪些系列文章目录提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:第一章Python机器学习入门之pandas的使用提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结前言提示:这里可以添加本文要记录的大概内容:例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例

    2022年9月18日
    0
  • sql存储过程简单例题_sql存储过程实例详解

    sql存储过程简单例题_sql存储过程实例详解1、创建存储过程P1,查询每个学生的修课门数,要求列出学生学号、姓名及修课门数。createprocP1asselectStudent.StudentID,StudentName,count(CourseID)选修门数fromStudentjoinGradeonGrade.StudentID=Student.StudentIDgroupbyStudent.StudentID,StudentNamego2、创建存储过程P2,查询学生的学号、姓名、课程名、成绩

    2022年8月30日
    0
  • 如何理解css中的float

    最近一段时间一直在为一个即将上线的新站进行一些前端开发。自然,对CSS的使用是必不可少的了。我们在CSS中很多时候会用到浮动来布局。常见的有float:left或者float:right。简单点来说,

    2021年12月20日
    50
  • 越狱软件源

    越狱软件源全部内容来源于网络。不对其内容的安全性负责,本人不承担任何责任。使用任何内容即表示同意此内容。软件源地址ios6五百年源apt.so/ios6vxios6分享源apt.feng/eq2wowMK越狱源apt.so/mksscc盗版暗影apt.so/anyinkeji杀手源apt.so/tanyao正版暗影apt.so/anyinkj…

    2022年6月9日
    78
  • c语言怎么使用strstr函数,c语言中strstr函数的用法是什么?[通俗易懂]

    c语言怎么使用strstr函数,c语言中strstr函数的用法是什么?[通俗易懂]c语言中“strstr(str1,str2)”函数用于判断字符串“str2”是否是“str1”的子串;如果是,则该函数返回“str2”在“str1”中首次出现的地址;否则返回NULL。其语法为“*strstr(str1,str2)”。strstr(str1,str2)函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。C语…

    2022年10月15日
    1

发表回复

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

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