1. 题目来源
2. 题目说明
3. 题目解析
方法一:模拟+逆序处理+巧妙解法
当然,转换数字的暴力方法,在 C++
是行不通的,但支持大数运算的 py
、java
,就可了。这道题也是通过人数极多。既然暴力不成,那就只能模拟,简单说下思路:
- 首先输入是一串二进制数字串,那么对于二进制字符串来讲,除 2 就相当于左移运算,加一的话就是正常加一并考虑进位即可。分别实现这两个方法即可
- 左移不太好考虑,我们可以换一种思想,从后向前考虑,将除 2 操作变成
index
指针的右移操作,避免了对字符串的过多操作 - 逆序遍历输入字符串,即从二进制低位向高位进行考虑,在此不考虑首位,会利于边界条件的判断
- 若当前位为字符 0,那么说明当前为偶数情况,就直接考虑逆序的下一位,及模拟左移操作,操作步数加 1
- 若当前位为字符 1,那么说明当前位奇数情况,需要进行加一的操作,就需要进行一个循环判断进位的方法
- 若当前位的前一位是字符 0,那么说明加 1 后不会再产生进位,只需要将前一位的字符 0 改为字符 1 即可
- 若当前位的前一位是字符 1,那么说明加 1 后仍会对前一位产生进位,则采用上述判断方法循环判断前一位即可,直至前一位为字符 0,修改后
break
跳出循环
- 在此,操作步数应该加 2 因为涉及到奇数加一的一步操作,并且也进行了一次移位操作。所以操作步数加 2
- 最后判断若输入字符串首位为字符 0,那么说明是由进位产生的,且当前为偶数 2,那么就再将操作步数加 1 即可得到答案
上面步骤详细,建议先直接看代码,不懂处进行对照,一看就能懂了啊。
参见代码如下:
// 执行用时 :4 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :6.5 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
int numSteps(string s) {
int len = s.size(), step = 0;
for (int i = len - 1; i > 0; --i) {
if (s[i] == '0') ++step;
else {
for (int j = i - 1; j >= 0; --j) {
if (s[j] == '1') s[j] = '0';
else {
s[j] = '1';
break;
}
}
step += 2;
}
}
if (s[0] == '0') return step + 1;
return step;
}
};