题号 | 题目 | 链接 |
---|---|---|
89 | Gray Code | https://leetcode.com/problems/gray-code/ |
137 | Single Number II | https://leetcode.com/problems/single-number-ii/ |
371 | Sum of Two Integers | https://leetcode.com/problems/sum-of-two-integers/ |
191 | Number of 1 Bits | https://leetcode.com/problems/number-of-1-bits/ |
461 | Hamming Distance | https://leetcode.com/problems/hamming-distance/ |
36 | Valid Sudoku | https://leetcode.com/problems/valid-sudoku/ |
50 | Pow(x, n) | https://leetcode.com/problems/powx-n/ |
190 | Reverse Bits | https://leetcode.com/problems/reverse-bits/ |
解体心得
No.89 格雷码 (AC)
- 格雷码的特点: 没两个相邻的格雷码仅有一位不同
- 格雷码的生成方式:1.递归生成: 当格雷码只有1位时,分别是0,1; 当格雷码为两位时,前2个格雷码是在0,1前加0前缀(00,01),后两个格雷码是加前缀1,同时将0,1反序(11,10),以此类推; 2. 异或生成 由二进制码生成格雷码是,从左边数第二位开始,Bi与Bi-1的异或是格雷码第i位上的值;
- 有格雷码反编码二进制码是:从左边数第二位开始,Bi与Bi-1的异或是二进制码第i位上的值。
No.137 唯一只出现一次的数字 (AC)(划重点)
- 本题需要特别注意有负数的情况
- 先统计32位每一位上数字出现的次数。然后看每一位是不是3的倍数,若不是,则该位是单独那个数字对应的位。找到单独的数字对应的所有位之后,即可将这个只出现一次的数字求出来。
- 关键问题是怎么求这个只出现一次的数字:
- Bug方法是:
res += pow(2, i)
; 这种方法在有负数的情况下会出bug - 正确方法: 完全用位运算实现,
res += (n[i] % 3) << 1
; 这里n[i] % 3
只可能是0或1,因此这里完全可以这样做,这样在有负数情况下也完全成立。
No.371 求两数之和 (AC)
- 参考题解: https://www.acwing.com/solution/LeetCode/content/543/
- 两数相“异或”,得到基本位;两数相“与”,得到进位。进位在做二次加法的时候需要左移以为再使用。需要特别注意的一点是, 存在为负的情况。 左移操作需要将原本进位的值转换成无符号数。
- 补充: 一个数的补码= 原二进制数按位取反后加1。由补码啊得到其真正表示的数,方法是先-1, 再按位取反。
No.191 计算一个数的二进制表示中1的个数 (AC)
- L按位循环32次,统计每一位是否为1. 具体方法是:
if (n >> i & 1 != 0) res++;
这里n >> i & 1
的含义是n
右移i
位后和000000000000000000000000000000000001
做与运算,其实也就是判断n
右移i
位后的最后1位是否为1.
No.461 求两个int类型的整数二进制位的值不相同的共有几位
- 按位枚举。
x >> 10 & 1
用于求x的第10位的值是0还是1
No.36 判断数独板是否行列和3*3区域都不包含重复1~9的数
- 位运算简化计算
- 用三个vector数组表示行、列和3*3区域中1~9是否有值
row[i] |= (1 << num);
No.50 幂运算 (AC)
- 快速幂优化解题速度,时间复杂度:logn
- 对于指数n, 现将其转换成正数,需要注意的是当 n = INT_MIN时, 用ans(n)会爆int,解决方法是,先用一个long类型的变量t存储n,再做接下来的操作
- 对于n分析其每一位二进制位是否为1, 若为1, 则乘于相应base,每循环一次,base自乘。
for( ; t; t >>= 1){
if (t & 1){
ans *= base;
}
base *= base;
}
No.190 翻转一个数的二进制表示 (AC)
- 循环32位,一次取出最低位,成为答案的最高位。
res = (res << 1) + (n >> i & 1);