引入
给你一个以二进制形式表示的数字 s 。请你返回按下述规则将其减少到 1 所需要的步骤数:
- 如果当前数字为偶数,则将其除以 2 。
- 如果当前数字为奇数,则将其加上 1 。
题目保证你总是可以按上述规则将测试用例变为 1 。
示例
输入:s = “1101”
输出:6
解释:“1101” 表示十进制数 13 。
Step 1) 13 是奇数,加 1 得到 14
Step 2) 14 是偶数,除 2 得到 7
Step 3) 7 是奇数,加 1 得到 8
Step 4) 8 是偶数,除 2 得到 4
Step 5) 4 是偶数,除 2 得到 2
Step 6) 2 是偶数,除 2 得到 1
输入:s = “10”
输出:1
解释:“10” 表示十进制数 2 。
Step 1) 2 是偶数,除 2 得到 1
输入:s = “1”
输出:0
题解
有一种方法叫模拟,直接模拟题目中的做法,计数,到1的时候跳出
-
如果当前数字为偶数,则将其除以 2 2 2。当 s s s 为二进制表示时,就相当于去除末尾的 0 0 0
-
如果当前数字为奇数,则将其加上 1 1 1。当 s s s 为二进制表示时,就相当于对末位加上 1 1 1(注意进位要求)
class Solution {
public:
int numSteps(string s) {
int steps = 0;
while (s != "1") {
//计数
++steps;
if (s.back() == '0') {
// 偶数的情况
s.pop_back();
}
else {
// 第一步:找出最低位的 0
// 第二步:把这个 0 变成 1,并将后面所有的 1 变成 0,这样就实现了 +1
// 特别地,如果 s 中全是 1,那么会有额外的进位
for (int i = s.size() - 1; i >= 0; --i) {
if (s[i] == '1') {
s[i] = '0';
if (i == 0) {
s = "1" + s;
break;
}
}
else {
s[i] = '1';
break;
}
}
}
}
return steps;
}
};
另一种解法
- 如果末位是0(偶数),则直接右移(除2)
- 如果末位是1(奇数),则需要加一,反应在二进制串上相当于不断进位,举几个例子
11001 -> 11010 -> 1101
1011 -> 1100 -> 110 -> 11
从以上例子可以看出,我们可以做的一个阶段性操作为:加1后,将末尾的0都去掉 ,总共需要的步骤数为: 1(进位) + 当前位起连续的1的个数(相当于进位后末尾新产生多少个0)
class Solution {
public:
int numSteps(string s) {
int idx = s.size()-1;
int ans = 0;
while(idx > 0)//第一位最后肯定剩1,不另计算
{
if(s[idx] == '0')
{
ans++;
idx--;
}
else
{
//进位+1
ans++;
while(idx >= 0 && s[idx] == '1')//进位后,连续进位(可能有1111->10000的情况)
{
ans++;
idx--;
}
if(idx > 0)
s[idx]='1';
}
}
return ans;
}
};