leetcode-位运算

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

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

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采用逻辑右移。
时间: 2024-10-17 16:28:15

leetcode-位运算的相关文章

Leetcode 位运算 Single Number

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Single Number Total Accepted: 20063 Total Submissions: 44658 Given an array of integers, every element appears twice except for one. Find that single one. Note: Your algorithm should have a linear

Leetcode 位运算 Single NumberII

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie Single Number II Total Accepted: 14224 Total Submissions: 43648 Given an array of integers, every element appears three times except for one. Find that single one. Note: Your algorithm should have

BitMap - leetcode [位运算]

136. Single Number 因为A XOR A = 0,且XOR运算是可交换的,于是,对于实例{2,1,4,5,2,4,1}就会有这样的结果: (2^1^4^5^2^4^1) => ((2^2)^(1^1)^(4^4)^(5)) => (0^0^0^5) => 5异或:异为1 137. Single Number II(黑人问号脸) 对于除出现一次之外的所有的整数,其二进制表示中每一位1出现的次数是3的整数倍,将所有这些1清零,剩下的就是最终的数.用ones记录到当前计算的变量

位运算总结&amp;拾遗

JavaScript 位运算总结&拾遗 最近补充了一些位运算的知识,深感位运算的博大精深,此文作为这个系列的总结篇,在此回顾下所学的位运算知识和应用,同时也补充下前文中没有提到的一些位运算知识. 把一个数变为大于等于该数的最小的2的幂 一个数为2的幂,那么该数的二进制码只有最高位是1. 根据这个性质,我们来举个栗子,比如有数字10,转为二进制码后为: 1 0 1 0 我们只需把 0 bit的位置全部用1填充,然后再把该二进制码加1就ok了.而x | (x + 1)正好可以把最右边的0置为1,可是

通过位运算求两个数的和(求解leetcode:371. Sum of Two Integers)

昨天在leetcode做题的时候做到了371,原题是这样的: 371. Sum of Two Integers Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Example: Given a = 1 and b = 2, return 3. 因为之前完全没有在实际练习中使用过位运算,所以刚看到这道题目的时候我的第一反应是 1.用乘除代替加减,但是一想,

LeetCode:位运算实现加法

LeetCode:位运算实现加法 写在前面 位运算符 实现加法的思路 两个加数,比如5(101)和6(110),如何不用加法就能得出两者之和呢? 我们知道二进制计算中,如果使用异或将会产生无进位的两者之和,而两数相与将会产生进位值!!! 可这样又如何呢? 1 sum = 011 2 carry =1000 两者继续异或将会产生 结果就出现了,此时无进位,所以进位为0时,sum将会为最终结果!因为此时不需要进位,异或运算就是最终结果! 优质代码 1 public int getSum(int a,

LeetCode刷题总结-双指针、位运算和分治法篇

本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. 独特字符串,难度困难 题号:923. 三数之和的多种可能,难度中等 2.实际场景应用问题 题号:826. 安排工作以达到最大收益,难度中等 3.元素对问题 题号:986. 区间列表的交集,难度中等 二.位运算 1.字符串和数组问题 题号:137. 只出现一次的数字 II,难度中等 题号:318.

[leetcode] Sum of Two Integers--用位运算实现加法运算

问题: Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -. Example: Given a = 1 and b = 2, return 3. 分析: 这里要求我们不能用加法.减法等运算符来实现加法运算.这里应该使用位运算来实现加法运算,实际上,这也是计算机CPU内部实现加法运算的方案. x XOR y真值表: x y output 0 0 0 0 1 1

[leetcode] Bitwise AND of Numbers Range(位运算)

不得不说位运算的应用都是很巧妙的. 这道题求一个连续区间整数的与运算的值,突破点在于连续的区间这个特点.我们可以先找几个数看一下规律, 2 3 4 5的二进制分别是 10 ,11,100,101,可以发现若m==n,则m为答案:当m!=n时,因为连续的两个数的二进制 的最后一位肯定不一样,与的值一定是0,前面相同的部分(1&1=1,0&0=0)保持. 所以我们每次先判断,不同的话就右移一位,比较前面的,直到相同的时候结束,最后左移  移动的位数. 不必担心左移的时候有1会导致溢出,从而失败

leetCode 342. Power of Four 位运算

342. Power of Four Given an integer (signed 32 bits), write a function to check whether it is a power of 4. Example:Given num = 16, return true. Given num = 5, return false. Follow up: Could you solve it without loops/recursion? 题目大意: 判断一个数是否为4的幂. 思路