Basic
知识点1 原码 反码 补码
最高位存符号位。
正数:原码=反码=补码 ;
负数:符号位不变,原码 –(取反)–> 反码 –(+1)–> 补码
浮点数的位表示
1
2
3
4
5
6 >>> 0.2+0.4==0.6
False
>>> 0.2+0.4
0.6000000000000001
# Python, Java(Double), Why not 0.6?
# tips:做浮点数的时候,知道有精度丢失这么个点
知识点2 位运算符
- Java 位运算符
位运算符号 | |
---|---|
& | 注意和逻辑运算符区别 && |
| | 逻辑运算符 || |
~ | 逻辑运算符 ! |
^ 异或 | 相异为1 相同为0 |
<< left shift | 补0, 会溢出的”*2” |
>> right shift | 补0或1,保持和最高位相同Why?”/2” |
>>> 无符号right shift | 补0 |
- Python 位运算符
位运算符号 | |
---|---|
& | and |
| | or |
~ | not |
^ 异或 | 相异为1 相同为0 |
<< left shift | 补0 无溢出的 “*2” |
>> right shift | 补0或1,保持和最高位相同 “/2” |
知识点3 空间优化
Contain Unique Letter Word
Determine whether a word contains all letters that are unique (no duplicate letters in the word).
- 1 HashSet
- 2 Array,256个ASCII码 长度256的Array
- 3 Bit Vector 充分利用空间!!
- xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 0~31th bit
- xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx 32~63th bit
- … …
318. Maximum Product of Word Lengths
给定一个字符串数组words,寻找length(words[i]) * length(words[j])的最大值,其中两个单词不包含相同字母。你可以假设每一个单词只包含小写字母。如果不存在这样的两个单词,返回0
- 1 Two words do not share common letters :Bit!
- 2 包含相同类型letter的word只用取长度最长的
1 | class Solution(object): |
异或^
- 两个相等的数经过异或运算会相互抵消
通常用来删除偶数个相同的数字,保留基数个个数的数字
Swap Two Integers
不建议在实际应用中采用
- 1 不一定比朴素方法快
- 2 a 和 b 引用同一变量
1 | void Swap(int &a, int &b) |
389. Find the Difference
给定两个字符串s和t,都只包含小写字母。字符串t由字符串s打乱顺序并且额外在随机位置添加一个字母组成。
寻找t中新增的那个字母。(和single number一样)1
2
3
4
5
6
7class Solution(object):
def findTheDifference(self, s, t):
res = 0
n = len(s)
for i in range(n):
res ^= ord(s[i]) ^ ord(t[i])
return chr(res ^ ord(t[n]))
268. Missing Number
给定一个包含从0, 1, 2, …, n, 选出的n个不同数字的数组,从中找出数组中缺失的那一个数。这里是少了一个数,single number 是多了一个数。1
2
3
4
5
6class Solution(object):
def missingNumber(self, nums):
ret = 0
for n in nums+range(len(nums)+1):
ret ^= n
return ret
136. Single Number
所有数字都出现偶数次,只有一个数字出现奇数次,求出现奇数次的那个数
解法1. HashSet
1
2
3
4
5
6
7
8
9
10# Time : O(n), Space : O(n)
class Solution(object):
def singleNumber(self, nums):
numSet = set()
for n in nums:
if n in numSet:
numSet.remove(n)
else:
numSet.add(n)
return list(numSet)[0]解法2.异或
1
2
3
4
5
6
7
8# Time : O(n), Space : O(1)
# 偶数次异或可以抵消
class Solution(object):
def singleNumber(self, nums):
ret = 0
for n in nums:
ret ^= n
return ret
137. Single Number II
所有数字出现三次,只有一个数字出现一次,求出现一次那个数。
解法1. HashTable
1
2
3
4
5
6
7
8
9
10
11
12
13# Time : O(n), Space : O(n)
class Solution(object):
def singleNumber(self, nums):
dic = {}
for n in nums:
if n in dic:
if dic[n] == 2:
del dic[n]
else:
dic[n] += 1
else:
dic[n] = 1
return dic.keys()[0]解法2. 用二进制模拟三进制运算
从一个bit出发考虑到32个bits
1 | cnt : 0 1 2 3 4 |
1 | # Time : O(n), Space : O(1) |
260. Single Number III
所有数字都出现两次,但是有两个数字只出现了一次。1
2
3
4a ^ a ^ b ^ b ^ c ^ d = c ^ d
0101 0100 c
1001 0010 d
1100 0110 c^d
- 把只出现一次的c和d分到两个组里
1 | class Solution(object): |
371. Sum of Two Integers
- 用^和&,构成加法运算
^表示相加后的结果,&后的<< 1表示相加后的进位
(理解加减法的位操作)
1 | // Iterative |
n & (n-1)
- 算是一个小trick!
- n&(n-1)可消除n中最右边(低位)的一个1
1 | 0101 1000 n |
191. Number of 1 Bits
统计一个整数用二进制表示时1的个数1
2
3
4
5
6
7
8
9// Java
public int hammingWeight(int n) {
int cnt = 0;
while (n != 0) {
cnt++;
n &= (n - 1);
}
return cnt;
}
231. Power of Two
判断一个数是不是2的n次幂1
2
3
40000 0001 2^0
0000 0010 2^1
0000 0100 2^2
0000 1000 2^3
1 | // Java |
326. Power of Three
- 也有一行代码更数学上tricky的方法:return n > 0 && 1162261467 % n == 0;
1 | // Java1 - Math |
342. Power of Four
1 | // Java1 for loop |
461. Hamming Distance
两个整数的汉明距离是指其二进制不相等的位的个数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class Solution(object):
def hammingDistance(self, x, y):
n = x ^ y # => Count bits of a number
cnt = 0
while n:
n &= (n-1)
cnt += 1
return cnt
def hammingDistance1(self, x, y):
n = x ^ y
cnt = 0
while n:
cnt += n & 1
n >>= 1
return cnt
477. Total Hamming Distance
两个整数的汉明距离是指其二进制不相等的位的个数, 计算给定的整数数组两两之间的汉明距离之和。
- 解法1. n^2 paris (TLE)
- 解法2. 拆解integer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# Time : O(32 * n), Space : O(1)
class Solution(object):
def totalHammingDistance(self, nums):
n = len(nums)
if n <= 1: return 0
res = 0
mask = 1
for _ in xrange(32):
cnt1 = 0
for num in nums:
if num & mask:
cnt1 += 1
mask <<= 1
res += (n - cnt1) * cnt1
return res
201. Bitwise AND of Numbers Range
1 | # [26, 30] |
仔细观察这个过程我们可以得出^_^,最后的结果是该范围内所有数的左边的共同部分,即公共左边首部(left header)1
2
3
4
5class Solution(object):
def rangeBitwiseAnd(self, m, n):
while m < n:
n &= n-1
return n
Advanced Topic
n & (-n)
n &-n returns the rightmost 1 bit in n., 属于第一次见,很难理解的小trick,这个会在Binary Indexed Tree中用到!
1 | n & (n ^ (n-1)) = n & (-n) |
正整数n的二进制表示中,只保留最低位的1的值!