forked from kamyu104/LeetCode-Solutions
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathminimum-one-bit-operations-to-make-integers-zero.py
68 lines (64 loc) · 1.74 KB
/
minimum-one-bit-operations-to-make-integers-zero.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Time: O(logn)
# Space: O(1)
# reference: https://en.wikipedia.org/wiki/Gray_code
class Solution(object):
def minimumOneBitOperations(self, n):
"""
:type n: int
:rtype: int
"""
def gray_to_binary(n):
result = 0
while n:
result ^= n
n >>= 1
return result
# [observation]
# n f(n)
# 000 0
# 001 1
# 011 2
# 010 3
# 110 4
# 111 5
# 101 6
# 100 7
# f(0XX...X) + f(1XX...X) = f(100...0) implies n is a gray code
# => f(n) is actually the inverse of gray code
return gray_to_binary(n)
# Time: O(logn)
# Space: O(1)
class Solution2(object):
def minimumOneBitOperations(self, n):
"""
:type n: int
:rtype: int
"""
# [observation1]:
# f(1) = 1
# f(10) = 2 * f(1) + 1 = 3
# f(100) = 2 * f(10) + 1 = 7
# by mathematical induction
# => f(2^k) = 2^(k+1)-1
#
# [observation2]
# n f(n)
# 000 0
# 001 1
# 011 2
# 010 3
# 110 4
# 111 5
# 101 6
# 100 7
# let pos be an array of positions where the bit is 1 in ascending order:
# f(0XX...X) + f(1XX...X) = f(100...0)
# f(1XX...X) = f(100...0) - f(0XX...X)
# = (2^(pos[k-1]+1)-1) - f(0XX...X)
# by mathematical induction
# => f(n) = (2^(pos[k-1]+1)-1) - (2^(pos[k-2])+1) + ... + (-1)^(k-1) * (2^(pos[0]+1)-1)
result = 0
while n:
result = -result - (n^(n-1)) # 2^(pos[i]+1)-1
n &= n-1
return abs(result)