LeetCode 405 - 数字转换为十六进制数


文章目录
- 摘要
- 描述
- 示例 1
- 示例 2
- 题解答案
- 题解代码分析
- 代码解析
- 示例测试及结果
- 时间复杂度
- 空间复杂度
- 总结
摘要
十六进制表示在我们日常开发中其实非常常见——不论是颜色代码(如 #ff6600)、内存地址、还是底层字节序列的可读展示,十六进制都是一种简洁高效的数值表达方式。
这道题要求我们手动实现一个整数到十六进制字符串的转换过程,不能直接调用语言自带的格式化函数。听起来像是“造轮子”,但其实这是一个非常实用的底层练习,有助于理解位运算、补码表示和数据编码。

描述
题目要求:
给定一个整数 num,返回它的十六进制字符串表示。
结果必须全部为小写字母,且没有前导零(除了数值为 0 的情况)。
另外一个细节是:
对于负数,我们需要按照 32 位补码(two’s complement) 的形式来表示结果。
示例 1
输入: num = 26
输出: "1a"
示例 2
输入: num = -1
输出: "ffffffff"
题解答案
这类题的核心是掌握整数与二进制、十六进制之间的转换关系。
我们知道:
- 十六进制的每一位可以由 4 个二进制位表示;
- 因此,一个 32 位整数刚好对应 8 个十六进制字符;
- 我们可以通过 按位与(&)操作 每次取出低 4 位,然后右移 4 位来逐步构造结果字符串。
算法流程如下:
-
如果 num 为 0,直接返回
"0"。 -
定义一个字符映射表
"0123456789abcdef"。 -
对 num 做 8 次循环:
- 取出低 4 位 (
num & 0xf); - 对应映射表取出字符;
- 将字符拼接在结果字符串前面;
- 右移 4 位;
- 如果 num 变为 0,可以提前结束。
- 取出低 4 位 (
-
对于负数,由于 Swift 的整数是有符号的,我们用
UInt32(bitPattern: Int32(num))将其按位 reinterpret 成无符号数,这样负数会变成它的补码形式。

题解代码分析
下面是完整可运行的 Swift 代码
import Foundationclass Solution {func toHex(_ num: Int) -> String {// 如果输入是 0,直接返回 "0"if num == 0 {return "0"}// 十六进制字符映射表let hexMap = Array("0123456789abcdef")// 使用 UInt32 重新解释 Int32 的位模式,处理负数补码var n = UInt32(bitPattern: Int32(num))var result = ""// 最多 8 位(32 bit ÷ 4 bit)while n != 0 {let index = Int(n & 0xf) // 取出最低 4 位result = String(hexMap[index]) + resultn >>= 4 // 右移 4 位}return result}
}// 示例调用
let solution = Solution()
print(solution.toHex(26)) // 输出: "1a"
print(solution.toHex(-1)) // 输出: "ffffffff"
print(solution.toHex(0)) // 输出: "0"
代码解析
逐行解释一下关键逻辑:
-
if num == 0:边界情况,必须单独处理。 -
UInt32(bitPattern: Int32(num)):- Swift 中
Int是有符号的; - 通过这种方式,可以把负数的二进制补码“按位”解读成无符号值;
- 比如
-1会变成0xffffffff。
- Swift 中
-
n & 0xf:每次取出最低 4 位(即 1 个十六进制位)。 -
n >>= 4:右移 4 位,相当于去掉刚刚处理过的低位。 -
字符串拼接:由于我们从低位开始取,所以要把新字符拼到结果字符串前面。
示例测试及结果
我们来测试几组不同的输入值:
print(solution.toHex(26)) // 期望: "1a"
print(solution.toHex(0)) // 期望: "0"
print(solution.toHex(255)) // 期望: "ff"
print(solution.toHex(-1)) // 期望: "ffffffff"
print(solution.toHex(305419896)) // 期望: "12345678"
输出结果如下:
1a
0
ff
ffffffff
12345678
所有测试通过
时间复杂度
我们每次处理 4 位,总共最多处理 32 位,因此:
时间复杂度:O(1)
(严格来说是常数时间,因为整数长度固定)
空间复杂度
除了一个字符串和映射表外,没有额外开销:
空间复杂度:O(1)
总结
这道题看似是算法题,但其实更像一个“小型位运算实战”。
通过手动实现十六进制转换,我们能更清楚地理解:
- 负数在计算机内部是如何用补码表示的;
- 位运算如何让数据转换更高效;
- 十六进制与二进制之间的天然映射关系。
在实际开发中,类似的逻辑可以用在:
- 调试时打印底层数据结构(比如网络包、字节缓冲区);
- 自定义序列化 / 加密算法;
- 构造调试用的内存地址、颜色、或标识符。
这类题虽然小,但非常有助于提升对“数与位”的直觉理解。
