位运算可以大大减小算法空间复杂度,提高效率,很巧妙!

先说一下位运算的简单用法

1. 按位与 &

用途:清零,取一个数中的某些指定位,保留一个数中的某些指定位

2. 按位或 |

用途:将一个数的某些位指定为1

3. 按位异或 ^

用途:交换两个数

a=a^b; b=a^b; a=a^b

让我们看看这三条语句执行后的结果:

第一条a=a^b,所以第二条b=a^b=(a^b)^b=a^(b^b)=a^0=a,现在b的值是a

第三条a=a^b=(a^b)^a=b^(a^a)=b^0=b,现在a的值是b啦!完成互换!

4. 取反 ~

5. 左移 << , 右移 >>

位运算最大的优点就是操作简单,效率高。可以看如下例子:

1. 假设一个变量有如下属性{输入,输出,类型,长度(如果是数组的话;如果不是数组那么长度为0)},试问你如何表示这个变量呢?

用一个结构体来表示这些属性?甚至用一个类?。。。嘿嘿,事实上只用一个int型就OK了。一个int型有32位,足够了,我们可以任意设置标志位的位置。比如第32位表示输出,第31位表示输入,第17-24位表示类型,第1-16位表示长度。好啦,如果一个变量是输入(则32位是1),不是输出(则31位是0),类型是char(假设char对应1,那么17-24位是00000001),长度是5,下面的int type可以表示全部信息:

int type=(1<<31)|(1<<16) |5

以后可以通过按位与来取得任何信息,比如要取得长度,可以type & 0x0000FFFF

2. 棋盘的表示:

选择什么样的数据结构可以表示一个棋盘呢?二维数组肯定是大多数人冒出的第一想法,不过二维数组操作起来不并像想象那么简单。如果棋盘是8*8的,实际上我们可以用一个64位长度的变量来表示棋盘。每一位对应棋盘的每一格。对于传统的只有黑白子的游戏,可以使用两个变量:第一个64位变量记录黑子的棋盘情况(如果棋盘的[i][j]位置有黑子,则第(i-1)*8+j位是1,否则是0),同样,第二个64位变量记录白子的棋盘情况。这样,判断棋子、吃子、翻转子等操作就可以用与、或、异或等位运算很方便高效地实现了。有些棋类游戏存在基本的“棋局”模式,而这个模式则可以用另一个变量记录。这个变量作为一个模版,可以与原棋盘变量进行位运算来判断原棋盘是否出现了这样一个特定的棋局模式。而如果用数组来表示棋盘,这些操作则会复杂许多。

而对于象棋这样的棋类游戏,棋子的种类并不是只有一黑一白的,应该要维持多个棋盘变量,具体可以参考以下链接:

http://www.elephantbase.net/computer/struct_bitboard.htm

1. 按位与运算 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。

  例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码) 00000001 (1的二进制补码)可见9&5=1。

  按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 运算 ( 255 的二进制数为0000000011111111)。

  应用:

  a. 清零特定位 (mask中特定位置0,其它位为1,s=s&mask)
  b. 取某数中指定位 (mask中特定位置1,其它位为0,s=s&mask)   2. 按位或运算 按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。   例如:9|5可写算式如下:   00001001|00000101
  00001101 (十进制为13)可见9|5=13   应用:   常用来将源操作数某些位置1,其它位不变。 (mask中特定位置1,其它位为0 s=s|mask)   3. 按位异或运算 按位异或运算符“^”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现,例如9^5可写成算式如下:   00001001^00000101 00001100 (十进制为12)   应用:   a. 使特定位的值取反 (mask中特定位置1,其它位为0 s=s^mask)
  b. 不引入第三变量,交换两个变量的值 (设 a=a1,b=b1)
  目 标 操 作 操作后状态
  a=a1^b1 a=a^b a=a1^b1,b=b1
  b=a1^b1^b1 b=a^b a=a1^b1,b=a1
  a=b1^a1^a1 a=a^b a=b1,b=a1   4. 求反运算   求反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。例如~9的运算为: ~(0000000000001001)结果为:1111111111110110   5. 左移运算   左移运算符“<<”是双目运算符。其功能把“<< ”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数, 高位丢弃,低位补0。 其值相当于乘2。例如: a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。   6. 右移运算   右移运算符“>>”是双目运算符。其功能是把“>> ”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。其值相当于除2。   例如:设 a=15,a>>2 表示把000001111右移为00000011(十进制3)。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统。移入0的叫逻辑右移,移入1的叫算术右移,Turbo C采用逻辑右移。

leetcode-位运算的更多相关文章

  1. leetcode - 位运算题目汇总(下)

    接上文leetcode - 位运算题目汇总(上),继续来切leetcode中Bit Manipulation下的题目. Bitwise AND of Numbers Range 给出一个范围,[m, ...

  2. leetcode - 位运算题目汇总(上)

    最近在看位运算的知识,十分感叹于位运算的博大精深,正好leetcode有 Bit Manipulation 的专题,正好拿来练练手. Subsets 给出一个由不同的数字组成的数组,枚举它的子数组(子 ...

  3. 78 leetCode 位运算解法

    按照自己的理解题目,数组内所有的组合:假如[1,2,3,4]看成1111到0000里面的排列组合,取位运算. vector<vector > subsets(vector&nums ...

  4. leetcode.位运算.136只出现一次的元素-Java

    1. 具体题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明:你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1 ...

  5. BitMap - leetcode [位运算]

    136. Single Number 因为A XOR A = 0,且XOR运算是可交换的,于是,对于实例{2,1,4,5,2,4,1}就会有这样的结果: (2^1^4^5^2^4^1) => ( ...

  6. leetcode 位运算异或

    1. 只出现一次的数字(136) 异或的性质总结: 相异为1,相同为0: a ^ a = 0; 0 ^ a = a; 如果 a ^ b = c 成立,那么a ^ c = b 与 b ^ c = a 均 ...

  7. JavaScript 位运算总结&拾遗

    最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个 ...

  8. 位运算总结&拾遗

    JavaScript 位运算总结&拾遗 最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识 ...

  9. LeetCode解题中位运算的运用

    位运算是我最近才开始重视的东西,因为在LeetCode上面刷题的时候发现很多题目使用位运算会快很多.位运算的使用包含着许多技巧(详细可以参考http://blog.csdn.net/zmazon/ar ...

  10. LeetCode编程训练 - 位运算(Bit Manipulation)

    位运算基础 说到与(&).或(|).非(~).异或(^).位移等位运算,就得说到位运算的各种奇淫巧技,下面分运算符说明. 1. 与(&) 计算式 a&b,a.b各位中同为 1 ...

随机推荐

  1. Windows API 之 FineFirstFile、FindNextFile

    参考:https://msdn.microsoft.com/en-us/library/aa364418%28VS.85%29.aspx FindFirstFile Searches a direct ...

  2. Python之路【第二篇】:Python基础(二)

    windows的换行符:\n\r linux的换行符:\n 文件的数据处理: r 以只读模式打开文件(默认模式)w 以只写模式打开文件a 以追加模式打开文件 r+b 以读写模式打开文件(以读/写方式打 ...

  3. 转 Android 编程下两种方式注册广播的区别

    常驻型广播 常驻型广播,当你的应用程序关闭了,如果有广播信息来,你写的广播接收器同样的能接收到,它的注册方式就是在你应用程序的AndroidManifast.xml 中进行注册,这种注册方式通常又被称 ...

  4. java-两个jre目录和三个lib目录-转

    lib目录下放置着jar包.程序中的import语句找的就是这些文件!例如:import javax.servlet.RequestDispatcher; 问题在于,在cmd模式下编译,系统会提示:C ...

  5. vim的复制粘贴小结(转)

    原文地址:http://lsong17.spaces.live.com/blog/cns!556C21919D77FB59!603.entry 内容: 用vim这么久 了,始终也不知道怎么在vim中使 ...

  6. HaiHongOJ 1003 God Wang

    题目连接:http://oj.haihongblog.com/problem.php?id=1003 线段树维护区间最小值,并且求解下标 #include <stdio.h> #inclu ...

  7. CSS3中transform几个属性值的注意点

    transform(变形)是CSS3中的元素的属性,transform的属性值主要包括旋转rotate.扭曲skew.缩放scale和移动translate以及矩阵变形matrix 基本用法可以参考文 ...

  8. js url编码函数

    JavaScript中有三个可以对字符串编码的函数,分别是: escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decod ...

  9. 最短路径问题 HDU 3790

    最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  10. 转 Encoding is Not Encryption 编码和加密的区别

    昨天跟别人聊天的时候,别人把base64说成了加密. 我并不是扣字眼,但是做为一个IT技术人员我认为分辨加密和编码的区别算是一个常识. It's unfortunate that the words  ...