bitmap以及异或运算法
一
有40亿个整数,再给一个新的整数,需要判断新的整数是否在1亿个整数中。
此处需要用到bitmap方法,每个整数用一个bit表示,1表示存在,0表示不存在。因此一个4字节的int=32个bit也就是可以表示32个数字,那么1亿个数字需要 100000000/32个int型。也就是需要申请100000000/32个字节的数组。需要耗费25M的内存。
这种方法也降低了数组需要的内存。
申请数组,N代表多少个数字,WORD代表一个int字节能表示多少位数字
#define WORD 32
#define SHIFT 5
#define MASK 0x1f
#define N 100000000
int bitmap[1 + N / WORD];
整型数组全部初始化为0.
void init_bitmap()
{
int size;
size = 1 + N / WORD;
memset(bitmap, 0, size);
}
将数字对应的Bit置为1。对于号码 89256,由于89256 mod 32=2789…8,这样我们应该置a[2789]中32位字符串的第8位(从低位数起)为1。SHIFT在这里表示右移的个数,i>>SHIFT就等于89256 mod 32=2789. MASK也就是16进制的31. i & MASK就等于i/32(求余操作)
void set(i)
{
bitmap[i >> SHIFT] |= (1<< (i & MASK));
}
判断是否存在,和前面用到的方法一样,不同的是这里运用的是与运算
int Judge_exist(i)
{
return bitmap[i >> SHIFT] & (1 << (i & MASK));
}
将对应的数代表的bit位清零
void clear(i)
{
bitmap[i >> SHIFT] &= ~(1 << (i & MASK));
}
二:
在不创建临时变量的情况下进行交换两个数。既然不能创建临时变量,那么就需要采取异或运算
对bit进行异或运算。
1 a^=b 将a和b bit中不一样的点位提取出来存入a
2 b^=a 将b中和a中不一样的点位取反,也就实现了b=a
3 a^=b 将a中和b不一样的点位取反,也就实现了a=b
例如a=3:0011 b=7:0111
a^=b a=0100
b^=a b=0011=3
a^=b a=0111=7
代码实现
void swap_without_temp(int *a, int *b)
{
(*a) ^= (*b);
(*b) ^= (*a);
(*a) ^= (*b);
}
三:
不进行移位操作判断数字的bit有多少个1
代码如下:
int count_bit_1(int a)
{
int count = 0;
while (a > 0)
{
count++;
a = a & a - 1;
}
return count;
}
n-1发生了什么
(1) 二进制数n,n-1后,如果最后一位是0,将向前一位借2,2-1=1。最后一位为1。如果前一位为0,将继续向前一位借2,加上本身少掉的1.则变为1。一直遇到1。减为0.
所以 二进制 xxxx10000-1 = xxxx01111
(2) n&n-1
按照上述 n=xxxx10000,n-1=xxxx01111
xxxx10000
xxxx01111
四
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。
找出那个只出现了一次的元素。 相同的值进行异或等于0,如果其余元素都出现两次,而只有一个元素出现一次,那么把数组中所有的
元素都进行异或运算
int findOnce(int arr[], int size)
{
int i;
int result;
result = 0;
for (i = 0; i < size; i++)
{
result ^= arr[i];
}
return result;
}
五
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。
1 首先将所有元素进行异或运算,得到的结果是仅出现一次的两个元素异或值
2 采用differ &= -differ 得到只出现在其中一个元素中的1个点位
3 用该点位去和数组中的元素做与运算。这个点位存在的所有数在一起做异或,这个点位不存在的所有数一起做异或
这样就可以将区分的做异或运算从而分别得到两个值
void findOnce_update(int arr[], int size,int *first,int *second)
{
int i;
int differ;
differ = 0;
for (i = 0; i < size; i++)
{
differ ^= arr[i];
}
differ &= -differ;
for (i = 0; i < size; i++)
{
if ((differ & arr[i]) == 0)
*first ^= arr[i];
else
*second ^= arr[i];
}
}
bitmap以及异或运算法的更多相关文章
- C# 异或校验算法
C# 的异或校验算法 直接上代码 public partial class FormCRC : Form { public FormCRC() { InitializeComponent(); } p ...
- Java运算符 算术运算法
运算符 算术运算法:+,-,*,/,%,++,– 复制运算符:= 关系运算符:>,<,>=,<=,==,!= instanceof 逻辑运算符:&&,||,! ...
- py02_04:三元运算法
a if a > b else c # a>b 成立,则为真,如果a>b为假,则返回c
- [Java 泥水匠] Java Components 之二:算法篇之项目实践中的位运算符(有你不懂的哦)
作者:泥沙砖瓦浆木匠网站:http://blog.csdn.net/jeffli1993个人签名:打算起手不凡写出鸿篇巨作的人,往往坚持不了完成第一章节. 交流QQ群:[编程之美 365234583] ...
- 不同的GCD算法
分类: C语言程序2014-10-08 15:10 28人阅读 评论(0) 收藏 举报 gcdC语言程序位运算 早在公元前300年左右,欧几里得就在他的著作<几何原本>中给出了高效的解法- ...
- 记一道有意思的算法题Rotate Image(旋转图像)
题出自https://leetcode.com/problems/rotate-image/ 内容为: You are given an n x n 2D matrix representing an ...
- 《OD学算法》排序
参考 http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html http://blog.csdn.net/wuxinyicomeon/ar ...
- C#中常用的排序算法的时间复杂度和空间复杂度
常用的排序算法的时间复杂度和空间复杂度 常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 ...
- STL函数模板(即算法)一览
查找算法 adjacent_find:找出一个串中第一个不符合次序的地方 find,find_if:找出第一个符合条件的元素 find_first_of:在一个串中寻找第一个与另一个串中任意一个元素相 ...
随机推荐
- Java 返回字符串中第一个不重复字符的下标 下标从0开始
比如abcdefgabdef 其中字符c和g不重复,返回c的小标,下标从0开始,那么是2 package com.example.demo; import org.testng.annotations ...
- Supermarket(贪心/并查集)
题目链接 原创的博客 题意: 超市里有N个商品. 第i个商品必须在保质期(第di天)之前卖掉, 若卖掉可让超市获得pi的利润. 每天只能卖一个商品. 现在你要让超市获得最大的利润. n , p[i], ...
- datediff(date1,date2) 函数的使用
版权声明:本文为博主原创文章,未经博主允许不得转载. 在MySQL中可以使用DATEDIFF()函数计算两个日期之间的天数 语法: datediff(date1,date2) 注:date1和date ...
- janusgraph-图数据库的学习(1)
图数据库的简介-来源百度百科 1.简介 图形数据库是NoSQL数据库的一种类型,它应用图形理论存储实体之间的关系信息.图形数据库是一种非关系型数据库,它应用图形理论存储实体之间的关系信息.最常见例子就 ...
- .Net Core 遇到 “'windows-1252' is not a supported encoding name.”
使用iTextSharp生成Pdf文件时报错如下: 'windows-1252' is not a supported encoding name. For information on defini ...
- pass的作用?
1.空语句 do nothing 2.保证格式完整,保证语义完整 3.占位语句
- IDEA设置类注释和方法注释模板
背景 在日常开发中,类和方法上希望有属于自己风格的注释模板,此文将记录如何设置IDEA类和方法注释模板. 注意:如果公司有统一的规范模板,请按照公司提供的规范模板去设置,这样可以统一代码注释风格.当然 ...
- java之大文件分段上传、断点续传
文件上传是最古老的互联网操作之一,20多年来几乎没有怎么变化,还是操作麻烦.缺乏交互.用户体验差. 一.前端代码 英国程序员Remy Sharp总结了这些新的接口 ,本文在他的基础之上,讨论在前端采用 ...
- pgloader 学习(五)pgloader 参考手册
pgloader将各种来源的数据加载到PostgreSQL中.它可以转换动态读取的数据,并在加载前后提交原始SQL. 它使用COPY PostgreSQL协议将数据流式传输到服务器,并通过填充一对re ...
- err Invalid input of type: 'dict'. Convert to a byte, string or number first
一个问题引发的血案: 用python向redis写入数据报错: redis.exceptions.DataError: Invalid input of type: 'dict'. Convert t ...