算法【位图】
创始人
2024-11-13 03:07:50

特别提醒:Python同学实现位运算的题目需要特别注意,需要自己去手动处理溢出和符号扩展等问题。比如:

(n << shift_amount) & 0xFFFFFFFF

一、位图原理

其实就是用bit组成的数组来存放值,用bit状态1、0代表存在、不存在,取值和存值操作都用位运算。限制是必须为连续范围且不能过大。好处是极大的节省空间,因为1个数字只占用1个bit的空间。

二、位图的实现

一个位图有以下几个函数:

// 初始化位图 只支持0~n-1所有数字的增删改查 Bitset(int n); // 把num加入到位图 void add(int num); // 把num从位图中删除 void remove(int num); // 如果位图里没有num 就加入  如果位图里有num 就删除 void reverse(int num); // 查询num是否在位图中 bool contains(int num);

代码如下。

class Bitset { public:     int *arr;     Bitset(int n);     ~Bitset();     void add(int num);     void remove(int num);     void reverse(int num);     bool contains(int num); };  Bitset::Bitset(int n) {     // 数组大小为n/32向上取整 可写成(n+31)/32     arr = new int[(n+31)/32]; }  Bitset::~Bitset() {     delete [] arr; }  void Bitset::add(int num){     arr[num/32] |= (1 << (num % 32)); }  void Bitset::remove(int num){     arr[num/32] &= ~(1 << (num % 32)); }  bool Bitset::contains(int num){     return ~((arr[num/32] & (1 << (num % 32))) == 0); }  void Bitset::reverse(int num){     if(contains(num)){         remove(num);     }else{         add(num);     } }

由于是用位代表一个数是否存在,所以一个int可代表32个数,则需要的int个数为n/32向上取整。对此可用(a + b -1)/b为a/b的向上取整来计算。对于一个数num,它被哪一个int代表由num/32得到下标,而具体的位则是由num%32得到。add方法中得到具体位数直接或进去,remove方法中得到具体的位数直接与进去。

下面有一个相关测试可以检验一下,按照题目要求修改部分即可。

测试链接:https://leetcode-cn.com/problems/design-bitset/

代码如下。

class Bitset { public:     // 根据数据量提前申请     int arr[3126] = {0};     // 是否翻转 false为没翻转 true为翻转     bool f;     // 记录1的个数     int cnt;     // 能代表多少个数     int nums;     Bitset(int size) {         f = false;         cnt = 0;         nums = size;     }      void fix(int idx) {         if(!f){             if(((arr[idx/32] >> (idx % 32)) & 1) == 0){                 arr[idx/32] |= (1 << (idx % 32));                 cnt++;             }         }else{             if(((arr[idx/32] >> (idx % 32)) & 1) == 1){                 arr[idx/32] &= ~(1 << (idx % 32));                 cnt++;             }         }     }          void unfix(int idx) {         if(!f){             if(((arr[idx/32] >> (idx % 32)) & 1) == 1){                 arr[idx/32] &= ~(1 << (idx % 32));                 cnt--;             }         }else{             if(((arr[idx/32] >> (idx % 32)) & 1) == 0){                 arr[idx/32] |= (1 << (idx % 32));                 cnt--;             }         }     }          void flip() {         f = !f;         cnt = nums - cnt;     }          bool all() {         return cnt == nums;     }          bool one() {         return cnt != 0;     }          int count() {         return cnt;     }          string toString() {         string s = "";         for(int i = 0;i < (nums + 31)/32;++i){             int cons = nums - i * 32 < 32 ? nums - i * 32 : 32;             for(int j = 0;j < cons;++j){                 if((!f && ((arr[i] >> j) & 1) == 1) || (f && ((arr[i] >> j) & 1) == 0)){                     s += '1';                 }else{                     s += '0';                 }             }         }         return s;     } };

其中,翻转使用一个变量代表,不需要每次遍历位图实现翻转。fix和unfix方法均分为翻转和未翻转两种情况。

相关内容

热门资讯

裸辞做“一人公司”,我后悔了 去年这个时候,一位以色列程序员正在东南亚旅行。他顺手把一个在脑子里转了很久的想法做成了产品,一个让任...
南京建成国内首个Pre-6G试... 4月21日,2026全球6G技术与产业生态大会在南京开幕。全息互动技术展台前,一名远在北京的工作人员...
超梵求职受邀参加“2025抖音... 超梵求职受邀参加“2025抖音巨量引擎成人教育行业生态大会”,探讨分享优质内容传播,服务万千学员。 ...
摩托罗拉Razr 2026(R... IT之家 4 月 22 日消息,摩托罗拉宣布新一代 Razr 折叠手机将于 4 月 29 日在美国发...
库克卸任,特纳斯领航:苹果新纪... 苹果首席执行官蒂姆·库克将卸任,硬件工程主管约翰·特纳斯将接任,苹果公司今天宣布此事。 库克将在夏季...