• 1404. 将二进制表示减到1的步骤数


    引入

    给你一个以二进制形式表示的数字 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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    另一种解法

    • 如果末位是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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 相关阅读:
    互联网医院系统源码:预约问诊小程序的开发方案详解
    关于React中的数据源绑定
    【Docker】Docker的使用案例以及未来发展、Docker Hub 服务、环境安全的详细讲解
    xlua源码分析(二)lua Call C#的无wrap实现
    Spring bean 和 Java Bean的区别
    第二章 进程与线程 七、处理机调度(概念、层次)
    CHAPTER 4: DESIGN A RATE LIMITER
    mysql数据库安装(详细)
    光流法大全
    雷达天线、信号链路、大气衰减基本概念
  • 原文地址:https://blog.csdn.net/Albert_weiku/article/details/125488071