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

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

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 2003】利用域&&组策略自动部署软件

    Windows 2003]利用域&&组策略自动部署软件 转自 http://hi.baidu.com/qu6zhi/item/4c0fa100dc768613cc34ead0 ==== ...

  2. STM32F2系列时钟的配置

    前一节详细介绍了系统默认的时钟配置,及各路时钟输出是多少,这是默认配置的,但实际使用的时钟默认的时钟并不符合要求,所以就得知道如何调用库函数进行配置. 最好的资料就是查阅stm32f2xx_rcc.c ...

  3. PHP无限极分类的几种方法

    导读:项目开发,经常栏目要做到无限极分类,几种方法PHP无限极分类的几种方法 复制代码 代码如下:namespace Util;class Category{static public functio ...

  4. Django: 之数据库导入、迁移和联用

    Django 数据库导入 从网上下载的一些数据,excel表格,xml文件,txt文件等有时候我们想把它导入数据库,应该如何操作呢? 以下操作符合 Django版本为 1.6 ,兼顾 Django 1 ...

  5. 转 Android开发者指南-Manifest.xml-<supports-screens

    <supports-screens> 版本:Android 3.2 语法: <supports-screensandroid:resizeable=["true" ...

  6. Byte数组和Int的互相转换

    public static int bytesToInt(byte[] bytes) { int addr = bytes[0] & 0xFF; addr |= ((bytes[1] < ...

  7. android KeyEvent for dot "."

    android连接了4x4的物理按键,需要映射".". 在linux驱动层注册了按键KEY_DOT, 写android的app的时候却没有对应的宏KEYCODE_DOT.只有KEY ...

  8. Super Jumping! Jumping! Jumping! 基础DP

    Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  9. oracle 主键自动增长

    oracle 主键自动增长 2009-12-11 16:07:00|  分类: 数据库资料|字号 订阅     这几天搞Oracle,想让表的主键实现自动增长,查网络实现如下: create tabl ...

  10. JAVA基础--super关键字

    子类对象new的时候堆里的内存分配: 1. 父类成员变量 2. 子类成员变量 3. this对象指向自己 4. super对象指向父类 super调用父类的方法: class FatherClass ...