位运算

LeetCode.191.位1的个数

六月ゝ 毕业季﹏ 提交于 2019-12-01 08:55:09
1.题目 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为 汉明重量 )。 示例 1: 输入:00000000000000000000000000001011 输出:3 解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。 示例 2: 输入:00000000000000000000000010000000 输出:1 解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。 示例 3: 输入:11111111111111111111111111111101 输出:31 解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。 2.解题思路 审题之后先明确了题目的目的是计算输入的无符号整数中 ’1‘ 的个数,所以我第一个想到用数组去做,利用循环去挨个判断是否是 ’1‘ ,并进行累加得出个数。但是后来在编译过程中发生了错误所以尝试另外一种方法,看了评论以及相关提示发现要使用 位运算 。因此利用循环和位运算的右移以及按位与运算 ‘&’ 来实现代码进行对 ‘1’ 的个数累积。(此处对位运算的理解还需优化) 3.代码 int hammingWeight(uint32_t n)

位运算

早过忘川 提交于 2019-12-01 08:31:21
1.算术移位指令 指令格式:SAL/SAR Reg/Mem, CL/Imm 左边的操作数可以使寄存器或内存,右边的操作数可以是寄存器cl或立即数 SAL(Shift Arithmetic Left): 算术左移 SAR(Shift Arithmetic Right): 算术右移 1)算术左移 左移一位,最高位存入cf,最低位补0; 例如:10000001左移一位 ->00000010 mov eax,0x81 sal eax,1 结果: eax=0x02,cf=1 2)算术右移 右移一位,最高位补符号位,最低位存入cf 例如:10000001右移一位 ->11000000 mov eax,0x81 sar eax,1 结果: eax=0xc0,cf=1 2.逻辑移位指令 指令格式:SHL/SHR Reg/Mem, CL/Imm SHL(Shift Left): 逻辑左移 SHR(Shift Right): 逻辑右移 shl逻辑左移:最高位存入cf最低位补0; shr逻辑右移:最低位存入cf,最高位补0; 3.循环移位指令 指令格式:ROL r/m, i8 ROR r/m, CL ROL(Rotate Left): 循环左移 ROR(Rotate Right): 循环右移 循环左移rol:最高位的值拿出来放到最低位,cf放最后拿出来的那个值 循环右移ror:最低位拿出来放最高位

N皇后解法以及位运算优化

丶灬走出姿态 提交于 2019-12-01 06:18:21
N皇后解法以及位运算优化 观察棋盘,要求皇后之间不能处在同行同列同一条斜线,求使得每行都有一个皇后的放置方法共有多少种。 每尝试放置一个皇后,都可以把该位置所在的行、列标号用一个数组标记,含义表示该行该列已经被占用,同时所在斜列也要进行标记。所在斜线有左斜线和右斜线两种,画个图解释一下。 对于左斜线(斜率为-1),假设坐标为 \((x,y)\) ,我们可以用 \(k = (x-y)\) 来表示,但是可能会有负数产生不利于用数组标记,所以我们给它加个 \(base = n\) (或者任何一个比n-1大的数字)即可 对于右斜线(斜率为1),假设坐标为 \((x,y)\) , 我们可以用 \(k = (x+y)\) 来表示 举个栗子,对于(2,0)这个点,他所在左斜线为 \(2-0 + n = 6\) (n=4),所在右斜线为 \(2+0 = 2\) ,那么在扫描第3行时,就避免尝试在这两条斜线上的点 标记原理清除之后,下一步就是搜索框架了 因为每行或者每列只会放一个皇后,所以我们用行号来作为一个搜索深度,每次搜索当前行的一个可行位置,对该位置所需要标记的都标记之后,进行下一行的搜索。 细节请见代码 #include <bits/stdc++.h> using namespace std; int n; int d[20],cols[20],dia[100],dia2[100]; int

fastjson SerializerFeature

一曲冷凌霜 提交于 2019-12-01 06:12:19
public enum SerializerFeature { /** * 对键加双引号 */ QuoteFieldNames, /** * 使用单引号代替双引号 */ UseSingleQuotes, /** * 输出空值(null) */ WriteMapNullValue, /** * 用枚举toString()值输出 */ WriteEnumUsingToString, /** * 用枚举name()输出 */ WriteEnumUsingName, /** * 对日期进行2016-09-23T23:11:56.550这样的格式化 */ UseISO8601DateFormat, /** * @since 1.1 * 如果一个List(实现了List接口)为null 则输出[] */ WriteNullListAsEmpty, /** * @since 1.1 * 如果一个字符串为null,则输出"" */ WriteNullStringAsEmpty, /** * @since 1.1 * 数字字段输出0 而不是null */ WriteNullNumberAsZero, /** * @since 1.1 * 如果一个Boolean变量为null,则输出false */ WriteNullBooleanAsFalse, /** * @since 1.1 *

位运算-状压DP 常用技巧

ⅰ亾dé卋堺 提交于 2019-12-01 05:23:48
目录 就想取个标题 取出x的第i位: 将x第i位取反 将x第i位变为1 将x第i位变为0 将x最靠右的1变成0 取出x最靠右的1 把最靠右的0变成1 判断是否有两个连续的1 枚举子集 @(目录) 就想取个标题 这些操作在状压DP中都很常用,灵活应用可以很好地降低码量,降低常数。 取出x的第i位: \(y\) = ( \(x\) >>( \(i\) - \(1\) ))& \(1\) ; 将x第i位取反 \(x\) ^= \(1\) <<( \(i\) - \(1\) ); 将x第i位变为1 \(x\) |= \(1\) <<( \(i\) - \(1\) ); 将x第i位变为0 \(x\) &= ~( \(1\) <<( \(i\) - \(1\) )); 将x最靠右的1变成0 \(x\) = \(x\) &( \(x\) -1); 取出x最靠右的1 \(y\) = \(x\) &(- \(x\) ); 这也是树状数组中我们熟知的 \(lowbit\) 把最靠右的0变成1 \(x\) |= \(x\) + \(1\) 判断是否有两个连续的1 \(if\) ( \(x\) &( \(x\) << \(1\) )) \(cout\) <<" \(YES\) "; 判断是否有 \(n\) 个连续的 \(1\) \(if\) ( \(x\) &( \(x\) << \(1\) )&& \

深入理解位运算操作及使用场景

孤街浪徒 提交于 2019-12-01 02:35:26
工作中一直没用过位操作,只有在阅读一些源码的时候会看到使用位运算符(因为直接使用位运算符效率更高),为了更好的阅读源码那就好好学习一下吧,顺便把学习的东西记下来! 所有的位运算都是在二进制下来进行运算的,再二进制下只有0/1。 1. ~ 位求反 运算符规则是:将运算符后二进制数反转,0变1,1变 0,所以对一个数取反偶数次结果是它本身。 例如: 0000 0000 0000 0000 0000 0000 0000 0011 -> 3 1111 1111 1111 1111 1111 1111 1111 1100 -> ~ 3 = -4 常用场景: 求相反数: ~a + 1 2. << 左移 运算符规则是:各二进位全部左移若干位,高位丢弃,低位补0。 例如:6 << 2 = 24 0000 0000 0000 0000 0000 0000 0000 0110 -> 6 0000 0000 0000 0000 0000 0000 0001 1000 -> 6 << 2 = 24 我们将6的二进位向左移动两位,低位补上两个0,高位丢弃,得出来的结果就是24。 常用场景: 左移常被用来做 * (2 ^ n)的运算,因为直接基于二进制运算,所以左移效率比 * (2 ^ n)高。 3. >> 右移 运算符规则是:各二进位全部右移若干位,正数高位补0,负数高位补1,低位丢弃。 例如: 12 >>

位运算的技巧

↘锁芯ラ 提交于 2019-11-30 18:19:26
异或(^) 运算规则:1,0→1 可以抽象的理解为 不进位加法 异或的性质: A^A=0 A^0=A 例题 :有一些数两两重复,除了一个数落单,不开辟额外空间,找到那个数。 思路:让数组内的所有数进行异或运算,最后的结果就是落单的数。 与(&) 运算规则:1,1→1 例题①:求一个二进制数1的个数 思路: 1.将数一直>>并与1进行与运算,为true就将个数+1。 2.一直对该数与该数-1进行与运算(-1后从低位开始到第一个1之间的所有0都变为1,第一个1变为0,这样与初始数与就可以把第一个变为0),直到这个数等于0,统计次数。 例题②:判断一个数是否是2的整数次方。 思路:要让这个数是2的整数次,那么这个数的二进制只有一个1。所以可以用用例题①的思路2来解,让这个数和这个数-1进行一次与运算,判断是否是0即可。 将二进制数奇偶位互换 思路:将这个数分别和0xaaaaaa (1010 1010 1010...取出偶数位) 0x555555 (0101 0101 0101...取出奇数位)作与(&)运算。再将保留偶数位的右移一位,保留奇数位左移一位,然后作异或(^)运算。 0-1之间浮点数的表示(乘2,挪整) 方法:整个数∗2,取出整数位(从左向右排布),再∗2,直到为0 。 举例:0.625 0.625∗2=1.25,取出1,则这个二进制数为0.1,该数变为0.25 0.25∗2

N皇后问题 --使用位运算解决

。_饼干妹妹 提交于 2019-11-30 18:13:28
关键位运算 x & (-x) 取得最低位1 x & (x-1) 去掉最低位1 class Solution(object): def totalNQueens(self, n): """ :type n: int :rtype: int """ if n < 1 : return [] self.count = 0 self.DFS(n,0,0,0,0) return self.count def DFS(self,n, row, cols, pie, na): if row >=n: self.count += 1 return # 得到当前所有的空位 bits = (~(cols | pie | na)) & ((1<<n)-1) while bits: p = bits & -bits # 取到最低位的1 self.DFS(n, row + 1, cols|p, (pie|p) <<1, (na|p)>>1) bits = bits & (bits - 1) # 去掉最低位的1 来源: https://www.cnblogs.com/yeni/p/11634467.html

二进制枚举法 位运算

偶尔善良 提交于 2019-11-30 17:00:37
首先需要知道位运算的基本操作: a<<i 表示a进行了i次乘2,即a的二进制数向后加了i个0 1<<3==1*2*2*2==2^3==8 ==> (1000) 2==(8) 1011<<1 ==22 ==> (11010)2==(22)10a>>i 表示a进行了i次除2,即a的二进制数向右移了i位11>>1 == 11/2==5 ==(101)2==(5)10 二进制枚举(1) int a=11; for(int i=0;i<4;i++) printf("%d",a>>i&1);   //数与1进行与操作,每次得到数末尾是1/0 1011 101 10 1& 1 & 1 & 1 & 1—————— ==》 ———— ==》 ———— ==》 ———— 0001 001 01 1得到的是1,1,0,1 即a二进制数的每个数,顺序相反,可以将其存入数组中 二进制枚举(2) int n; for(int i=0;i<(1<<n);i++) //枚举2^n -1 种情况 printf("%d",i);     来源: https://www.cnblogs.com/Theo-sblogs/p/11605121.html

关于bitset

假装没事ソ 提交于 2019-11-30 16:51:15
当我们遇到这样一种情况: 输入n串二进制数 然后对这些二进制数进行一些位运算 再以二进制输出 一般我们会想到用字符串输入这些二进制数然后转存进int或者long long进行位运算 最后再写一个输出二进制的函数用来输出 乍一看,难度不大,码量也还行 但是也没有一种数据结构能够直接存储二进制数呢 答案肯定是有的 不然我BB半天是为了什么 bitset是C++自带的用来储存二进制数的一种数据结构(在bitset头文件中) 它的好处是能够直接用来读入二进制数和进行位运算 但是不能读二进制以上的数 并且int类型和bool类型可以转换为bitset(long long之类的整型也可以) 但是字符数组依然不行 bitset还有一个好处就是空间小,一个元素只占1bit,只有char的1/8大 bitset中的每一个元素都可以被单独访问,但是不能被单独读入或读出 bitset还自带了一些函数(如果有遗漏请指出): bitset <10> s; s.any(); //返回在bitset中是否存在1(即bitset存储的二进制数是否不为0) s.set(); //将bitset所有的元素全部变为1 s.set(p); //将bitset的第p+1个元素变为1 s.set(p, x); //将bitset的第p+1个元素变为x(x为1或0) s.flip(); //将bitset中所有的元素全部取反