题目描述

[!green]

牛客原题: ✅ 补充题 145. 有符号整数的进制转换

给定 32 位整数 M 与基数 base,其中 2≤base≤16,返回对应的进制表示,使用大写字母 A…F。

负数保留负号,不输出补码。

示例 1:

输入: M = -31, base = 16
输出: "-1F"
解释: 31 的十六进制表示为 1F,负数在前面保留负号。

示例 2:

输入: M = 10, base = 2
输出: "1010"
解释: 10=1×2³+0×2²+1×2+0。

提示:

  • M 为 32 位整数。
  • 2≤base≤16。
  • 10…15 用大写 A…F 表示,负数保留负号。

题意分析

把 32 位有符号整数写成指定基数的数位序列,保留负号,10 到 15 对应大写 A 到 F。手撕时需要说明如何逐位取得数字,以及如何处理 0 和最小负整数。

解法:不断除基数取余并反转数位

核心思路

[!blue]

对非负数有 value = (value / base) * base + value % base,余数恰好是最低数位,商表示去掉这一位后的高位部分。反复取余并整除,直到商为 0,就从低到高取得全部数位。

用字符表 0123456789ABCDEF 将余数映射为输出字符,最后反转以恢复高位在前的顺序。负号不参与进制换算,在反转前追加到末尾,反转后就出现在最前面。

必须先将 32 位输入提升为 64 位再取相反数,才能表示最小负整数的绝对值。循环至少执行一次,使输入 0 产生字符 0,而不是空字符串。

解题步骤

  1. 将 32 位输入提升到 64 位,记录符号后转成非负值。
  2. 反复输出 value%base 对应的数字字符,并令 value/=base。
  3. 负数补上负号后反转;零值也执行一轮输出 0。

代码实现

class Solution {
    public String convert(int m, int base) {
        String digits = "0123456789ABCDEF";
        long value = m;
        boolean negative = value < 0;

        if (negative) {
            value = -value;
        }

        StringBuilder out = new StringBuilder();

        do {
            out.append(digits.charAt((int) (value % base)));
            value /= base;
        } while (value > 0);

        if (negative) {
            out.append('-');
        }

        return out.reverse().toString();
    }
}
func convert(m, base int) string {
    digits := "0123456789ABCDEF"
    value := int64(m)
    negative := value < 0
    if negative {
        value = -value
    }
    out := []byte{}
    for {
        out = append(out, digits[value%int64(base)])
        value /= int64(base)
        if value == 0 {
            break
        }
    }
    if negative {
        out = append(out, '-')
    }
    for i, j := 0, len(out)-1; i < j; i, j = i+1, j-1 {
        out[i], out[j] = out[j], out[i]
    }
    return string(out)
}

复杂度分析

  • 时间复杂度:$O(d)$。
  • 空间复杂度:结果存储空间 $O(d)$。

设输出数字位数为 d。0 也输出一位;32 位输入在二进制下至多 32 个数字位,另有负号。

关键点总结

[!green]

取余得到最低位,整除去掉最低位;符号与数位分开处理,可以同时覆盖零值和最小负整数。

易错点总结

[!yellow]

  • 先提升到 64 位再取正值,不能对 32 位最小负数直接求 int 绝对值。
  • 0 也要至少输出一位,因此使用至少执行一次的取余循环。
  • 负号独立处理,本题不输出固定宽度的二进制补码。

相似题目

题目 难度 关联与区别
405. 数字转换为十六进制数 简单 原题负数输出补码十六进制,本题按任意给定基数输出带负号的绝对值数位。
168. Excel 表列名称 简单 同样反复取余确定低位;Excel 列名是从 1 开始的无零数码体系,除余前需要调整偏移。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2026/63630085
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!