给你一个整数 n
,你需要重复执行多次下述操作将其转换为 0
:
- 翻转
n
的二进制表示中最右侧位(第0
位)。 - 如果第
(i-1)
位为1
且从第(i-2)
位到第0
位都为0
,则翻转n
的二进制表示中的第i
位。
返回将 n
转换为 0
的最小操作次数。
示例 1:
输入:n = 3 输出:2 解释:3 的二进制表示为 "11" "11" -> "01" ,执行的是第 2 种操作,因为第 0 位为 1 。 "01" -> "00" ,执行的是第 1 种操作。
示例 2:
输入:n = 6 输出:4 解释:6 的二进制表示为 "110". "110" -> "010" ,执行的是第 2 种操作,因为第 1 位为 1 ,第 0 到 0 位为 0 。 "010" -> "011" ,执行的是第 1 种操作。 "011" -> "001" ,执行的是第 2 种操作,因为第 0 位为 1 。 "001" -> "000" ,执行的是第 1 种操作。
提示:
0 <= n <= 109
方法一:递归
通过找规律可以发现动态规划转移方程如下:
其中
class Solution:
def minimumOneBitOperations(self, n: int) -> int:
if n <= 1:
return n
for i in range(64):
if (n >> i) == 1:
base = 1 << i
break
return 2*base-1 - self.minimumOneBitOperations(n-base)
func minimumOneBitOperations(n int) int {
if n <= 1 {
return n
}
base := 0
for i := 0; i < 64; i++ {
if (n >> i) == 1 {
base = 1 << i
break
}
}
return (base << 1) - 1 - minimumOneBitOperations(n-base)
}