top1编程
← 返回题目
题解

二进制转八进制

1 条题解

  • 0
    @ 2026-8-5 12:17:20

    解题思路

    这道题和"二进制转十六进制"思路一样,只是分组大小不同:1位八进制数,正好用3位二进制数表示。 因为3位二进制数最小是 000(0),最大是 111(7),正好对应八进制的一位 0~7。

    和十六进制题不同的地方:二进制长度不一定是 3 的倍数,所以先要在最左边补 0,把长度补成 3 的倍数。 比如 101110010 长度是 9,正好是 3 的倍数;如果长度是 4 的 1011,前面补 0 变成 001011。

    具体做法:

    1. 读入二进制字符串 s。
    2. 用 while 循环在开头补 0,直到长度是 3 的倍数:s = "0" + s。
    3. 每 3 位一组,把这一组二进制数转成十进制数值 v(范围一定是 0~7),直接输出这个数字就是八进制的一位。
    4. 去掉前导0:最前面一组如果是 000,不要输出(比如 00111 应输出 7 而不是 07);如果全是 0 就输出一个 0。

    用样例验证:101110010 分成 101 110 010:

    • 101 → 1×4+0×2+1=5
    • 110 → 1×4+1×2+0=6
    • 010 → 0×4+1×2+0=2

    结果就是 562,和样例一致。

    参考代码

    #include <iostream>
    using namespace std;
    // 用途:把二进制整数转换成八进制整数(长度不超过2000)
    int main() {
        string s;
        cin >> s;
        // 每3位二进制数对应1位八进制数,先把长度补成3的倍数(前面补0)
        while (s.size() % 3 != 0) s = "0" + s;
        bool started = false;            // 是否已经开始输出(用来去掉前导0)
        // 每3位一组转换成八进制数字
        for (int i = 0; i < s.size(); i += 3) {
            int v = 0;                    // v 存放这一组3位二进制数的值
            for (int j = 0; j < 3; j++)   // 逐位累加
                v = v * 2 + (s[i + j] - '0');
            if (!started && v == 0) continue;  // 前导的0组不输出
            started = true;
            cout << v;                    // v 的范围是 0~7,正好是八进制数字
        }
        if (!started) cout << '0';        // 全是0时输出一个0
        cout << endl;
        return 0;
    }
    

    复杂度分析

    • 时间复杂度:二进制数长度最多 2000,每个字符只处理一次,所以是 O(n),其中 n 是二进制数的位数。
    • 空间复杂度:用一个字符串存输入,补0最多多出2位,所以是 O(n)。

    长度 2000 也完全能在一瞬间算完。

    • 1