LeetCode 1611. 使整数变为 0 的最少操作次数
Posted 英雄哪里出来
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 1611. 使整数变为 0 的最少操作次数相关的知识,希望对你有一定的参考价值。
文章目录
一、题目
1、题目描述
给你一个整数 n n n,你需要重复执行多次下述操作将其转换为 0 0 0 :
1)翻转 n n n 的二进制表示中最右侧位(第 0 0 0 位)。
2)如果第 ( i − 1 ) (i-1) (i−1) 位为 1 1 1 且从第 ( i − 2 ) (i-2) (i−2) 位到第 0 0 0 位都为 0 0 0,则翻转 n n n 的二进制表示中的第 i i i 位。
返回将 n n n 转换为 0 0 0 的最小操作次数。
样例输入:n = 3
样例输出:2
2、基础框架
- C语言 版本给出的基础框架代码如下:
int minimumOneBitOperations(int n)
3、原题链接
二、解题报告
1、思路分析
(
1
)
(1)
(1)
1
1
1 通过
1
1
1 次 变成
0
0
0;
(
2
)
(2)
(2)
10
10
10 通过先变成
11
11
11,再翻转最高位变成
01
01
01,然后变成
0
0
0,总共 3 次;
(
3
)
(3)
(3)
100
100
100 通过 3次变成
110
110
110,再翻转最高位变成
010
010
010,再三次变成
0
0
0,总共 7 次;
(
4
)
(4)
(4) 根据数学归纳法,我们发现,对于
1
0...0
⏟
k
1\\underbrace0...0_k
1k
0...0,变到
0
0
0 的次数为
2
k
+
1
−
1
2^k+1 - 1
2k+1−1 次;
(
5
)
(5)
(5) 然后我们对一个数
n
n
n 进行二进制分解
n
=
(
101011
)
2
n = (101011)_2
n=(101011)2 ,那么我们必须先想办法把最高位的
1
1
1 变成
0
0
0,于是就转化成了求将
(
01011
)
2
(01011)_2
(01011)2 转化为
(
10000
)
2
(10000)_2
(10000)2 的最少步数;而对于
(
01011
)
2
(01011)_2
(01011)2 要转化成
(
10000
)
2
(10000)_2
(10000)2,又可以转化成将
(
1011
)
2
(1011)_2
(1011)2 转化成
(
1000
)
2
(1000)_2
(1000)2 的最少步数;然后就是
(
011
)
2
(011)_2
(011)2 要变成
(
000
)
2
(000)_2
(000)2, 也就是
(
11
)
2
(11)_2
(11)2 变成
(
00
)
2
(00)_2
(00)2;
(
6
)
(6)
(6) 于是得出算法:
(
6.1
)
(6.1)
(6.1) 首先将
n
n
n 进行二进制分解;
(
6.2
)
(6.2)
(6.2) 一个数如果要变到
1
0...0
⏟
k
1\\underbrace0...0_k
1k
0...0 ,则调用递归dfs1(n)
;如果要变到
0
0
0,则调用递归dfs2(n)
,于是递归求解dfs2(n)
就是答案了。
2、时间复杂度
最坏时间复杂度 O ( l o g 2 n ) O(log_2n) O(log2n) 。
3、代码详解
int dfs1(int *bit, int d); // (1)
int dfs2(int *bit, int d); // (2)
int dfs1(int *bit, int d)
if(d == 0)
return bit[0] ^ 1;
if(!bit[d])
return dfs1(bit, d-1) + 1 + ( (1<<d) - 1 );
return dfs2(bit, d-1);
int dfs2(int *bit, int d)
if(d == 0)
return bit[0];
if(bit[d])
return dfs1(bit, d-1) + 1 + ( (1<<d) - 1 );
return dfs2(bit, d-1);
int minimumOneBitOperations(int n)
if(n == 0)
return 0;
int stk[100], top = 0;
while(n)
stk[top++] = n & 1;
n >>= 1;
return dfs2(stk, top-1);
-
(
1
)
(1)
(1)
int dfs1(int *bit, int d)
表示 b i t [ d : 0 ] → 1 0...0 ⏟ d bit[d:0] \\to 1\\underbrace0...0_d bit[d:0]→1d 0...0 的最少步数; -
(
2
)
(2)
(2)
int dfs2(int *bit, int d)
表示 b i t [ d : 0 ] → 0 0...0 ⏟ d bit[d:0] \\to 0\\underbrace0...0_d bit[d:0]→0d 0...0 的最少步数; -
(
3
)
(3)
(3) 对于这两个函数,判断
bit[d]
这一位和要求的位是否一致,如果不一致,则需要利用规则二进行翻转;如果一直,则继续计算 b i t [ d − 1 : 0 ] → 0 0...0 ⏟ d − 1 bit[d-1:0] \\to 0\\underbrace0...0_d-1 bit[d−1:0]→0d−1 0...0 的最少步数;
三、本题小知识
递归求解某个问题的时候,抽象出中间步骤,会清晰许多;
四、加群须知
相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」。
那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:
如果链接被屏蔽,或者有权限问题,可以私聊作者解决。
大致题集一览:
LeetCode~945.使数组唯一的最小增量