leetcode 1611. 使整数变为 0 的最少操作次数

 

给你一个整数 n,你需要重复执行多次下述操作将其转换为 0 :

翻转 n 的二进制表示中最右侧位(第 0 位)。
如果第 (i-1) 位为 1 且从第 (i-2) 位到第 0 位都为 0,则翻转 n 的二进制表示中的第 i 位。
返回将 n 转换为 0 的最小操作次数。

 

示例 1:

输入:n = 0
输出:0
示例 2:

输入:n = 3
输出:2
解释:3 的二进制表示为 "11"
"11" -> "01" ,执行的是第 2 种操作,因为第 0 位为 1 。
"01" -> "00" ,执行的是第 1 种操作。
示例 3:

输入:n = 6
输出:4
解释:6 的二进制表示为 "110".
"110" -> "010" ,执行的是第 2 种操作,因为第 1 位为 1 ,第 0 到 0 位为 0 。
"010" -> "011" ,执行的是第 1 种操作。
"011" -> "001" ,执行的是第 2 种操作,因为第 0 位为 1 。
"001" -> "000" ,执行的是第 1 种操作。
示例 4:

输入:n = 9
输出:14
示例 5:

输入:n = 333
输出:393
 

提示:

0 <= n <= 109

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-one-bit-operations-to-make-integers-zero
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


二进制中 1 的位置映射的值,加减交替计算(九连环的模型)。


1:这道题的模型就是九连环。

2:创建模型, 若只有第 i 位为 1,其他的位置为 0, 则要反转 第i位,需要先把第 (i- 1)位反转位1,再反转第i位,再把(i- 1)位反转位0

3:所以 f(n) = 2 * f(n - 1) + 1, 其中f(1) = 1;

4:所以若只有第 i 位为 1,其他的位置为 0, 则f(n) = 2 ^ (i + 1) - 1 或者用位运算表示 f(n) = (2 << i) - 1

例如 n = 333, 则其二进制数字为: 101001101

设置反转次数为 sum = 0;

第8位:反转第8位的1,需要反转 511次, sum = sum + 511 = 511;

第6位:但是 第6位已经有了 1,不需要再反转了,可以需要减去反转第6位的127次。 sum = sum - 127 = 384;

第3位:而需要第6位起作用,其前面都不能为 1,只能为0,所以需要先把第3位的1,反转位0,反转第3位需要操作15次,sum = sum + 15 = 399;

第2位:同理,若是操作第3位,第2位已经有了,不用再操作他的7次。所以 sum = sum - 7 = 392次。

第0位:同理, 若是第2位起作用,其前面都必须为0,所以第0为先反转为0,需要操作一次。 sum = sum + 1 = 393

以上规律,就是 二进制种,遇到 1 的时候,就可以 + - + - 的交替计算,加减的值为(2 << i) - 1计算。
    public int minimumOneBitOperations(int n) {
        String s = Integer.toBinaryString(n);
        byte[] bytes = s.getBytes();
        int length = s.length();
        int sum = 0;
        boolean flag = true;
        for (int i = 0; i < length; i++) {
            if (bytes[i] == 49) {
                if (flag) {
                    sum += ((2 << (length - 1 - i)) - 1);
                } else {
                    sum -= ((2 << (length - 1 - i)) - 1);
                }
                flag = !flag;
            }
        }
        return sum;
    }

 
posted @ 2021-08-21 15:39  旺仔古李  阅读(315)  评论(0编辑  收藏  举报