力扣1611——使整数变为 0 的最少操作次数(简单易懂版)
难度

题目
给你一个整数 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 种操作。
提示
代码
测试用例
测试用例
测试结果
1611. 使整数变为 0 的最少操作次数
已解答
困难
相关标签
premium lock icon
相关企业
提示
给你一个整数 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 <= 10^9
思路:
从任意数字的二进制操作为0,考虑任意数字的逆过程:从0到任意数字
0->1->11->10->110->111->101->100->1100->1101->1111->1110->1010->1011->1001->1000
易发现从0到1操作1次,0到10操作3次,0到100操作7次,0到1000操作15次,设f(x)为任意数字的操作次数
- f ( 2 ^ 0 ) = 1
- f ( 2 ^ 1 ) = 3
- f ( 2 ^ 2 ) = 7
- f ( 2 ^ 3 ) = 15
易得 - f ( 2 ^ k ) = 2 ^ ( k + 1) - 1
对于任意非2次幂例如
二进制1010(十进制10) - f ( 10 ) = f ( 2 ^ 3 ) - f ( 2 )
二进制1111(十进制15) - f ( 15 ) = f ( 2 ^ 3 ) - f ( 7 ) = f ( 2 ^ 3 ) - f ( 15 - 2 ^ 3 )
- f ( 7 ) = f ( 2 ^ 2) - f ( 3 ) = f ( 2 ^ 2 ) - f ( 7 - 2 ^ 2 )
- f ( 3 ) = f ( 2 ^ 1) - f ( 1 ) = f ( 2 ^ 1 ) - f ( 3 - 2 ^ 1)
代码
public int minimumOneBitOperations(int n) {if(n == 0)return 0;int count_zeros = 32 - Integer.numberOfLeadingZeros(n);int count = (1 << count_zeros) - 1;return count - minimumOneBitOperations(n - (1 << (count_zeros- 1)));}
结果

