数学解题技巧

  • 加减乘除求余
  • 边界问题
  • 位运算
  • 数学方法
  • 整型方法
  • 正负判断
  • 进制
  • 幂运算

位运算

基本的位运算知识:

// 与运算(&)
0 & 0 = 0;
1 & 1 = 1;
1 & 0 = 0;
// 或运算(|)
0 | 0 = 0;
1 | 0 = 1;
1 | 1 = 1;
// 异或运算(^)
1 ^ 1 = 0;
1 ^ 0 = 1;
0 ^ 0 = 0;

常用技巧:

  • n & (n - 1) 能够消灭 n 中最右侧一个 1
  • 右移:除以 2;左移:乘以 2
  • 异或性质:交换律,0 ^ n = nn ^ n = 0
  • 我们可以将常用字符、数字等均转为按位运算,可以节约空间

位运算常用技巧

操作说明变化操作
去掉最后一位101101 -> 10110n >> 1
在最后加一个 0101101 -> 1011010n << 1
在最后加一个 1101101 -> 1011011(n << 1) + 1
把最后一位变成 1101100 -> 101101n | 1
把最后一位变成 0101101 -> 101100(n | 1) - 1
最后一位取反101101 -> 101100n ^ 1
把右数第 K 位变成 1101001 -> 101101k=3n | (1 << (k-1))
把右数第 K 位变成 0101101 -> 101101k=3n & ~(1 << (k-1))
右数第 k 位取反101001 -> 101101k=3n ^ (1 << (k-1))
取末三位1101101 -> 101n & 7
取末 k 位1101101 -> 1101k=5n & (1 << k-1)
取右数第 k 位1101101 -> 1k=4n >> (k-1) & 1
把末 k 位变成 1101001 -> 101111k=4n | (1 << k-1)
末 k 位取反101001 -> 100110k=4n ^ (1 << k-1)
把右边连续的 1 变成 0100101111 -> 100100000n & (n + 1)
把右起第一个 0 变成 1100101111 -> 100111111n | (n + 1)
把右边连续的 0 变成 111011000 -> 11011111n | (n - 1)
取右边连续的 1100101111 -> 1111(n ^ (n + 1)) >> 1
去掉右起第一个 1 的左边100101000 -> 1000n & (n ^ (n - 1))

左移运算

a << b 的值实际上就是 a 乘以 2 的 b 次方,a << b 表示把 a 转为二进制后左移 b 位(在后面添加 b 个 0)。

右移运算

a >> b 表示二进制右移 b 位(去掉末 b 位),相当于 a 除以 2 的 b 次方(取整)。

相关题目

  • 汉明距离相关题目
    • 191 - 位 1 的个数
    • 461 - 汉明距离
    • 477 - 汉明距离总和
  • 只出现一次的数字相关题目
    • 136 - 只出现一次的数字
    • 137 - 只出现一次的数字 ii
    • 260 - 只出现一次的数字 iii
  • 反转相关题目
    • 190 - 颠倒二进制位
    • 476 - 数字的补数
  • 全组合相关题目
    • 78 - 子集
  • 数学相关题目
    • 29 - 两数相除
    • 201 - 数字范围按位与
    • 371 - 两整数之和
  • 其他类型题目
    • 693 - 交替位二进制数

相关题目

  • 1290 二进制链表转整数
  • 191 位 1 的个数(与运算后右移)
  • 汉明距离(异或运算)
  • 338 比特位计数(位运算+DP)
  • 190 颠倒二进制位
  • 136 只出现一次的数字(经典异或运算)
  • 137 只出现一次的数字 II(有限状态自动机 + 异或)

进位

const v1 = 9,
v2 = 9,
carry = 0,
remainder = 0;
// 总数
const total = v1 + v2 + carry;
// 进位
carry = Math.floor(total / 10);
// 当前位数值
remainder = total % 10;