数字转换为十六进制数

标签: 位运算 数学

难度: Easy

给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。

注意:

  1. 十六进制中所有字母(a-f)都必须是小写。
  2. 十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。 
  3. 给定的数确保在32位有符号整数范围内。
  4. 不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。

示例 1:

输入:
26

输出:
"1a"

示例 2:

输入:
-1

输出:
"ffffffff"

Submission

运行时间: 20 ms

内存: 0.0 MB

class Solution:
    def toHex(self, num: int) -> str:
        # 如果是负数则转化成补码
        if num < 0:
            num += 2 ** 32
        
        stack = []
        s = "0123456789abcdef"
        
        while num:
            stack.append(s[num % 16])
            num //= 16
        
        if not stack:
            return "0"
        
        stack.reverse()
        return "".join(stack)

Explain

这个题解使用了除以16取余数的方法来将十进制数转换为十六进制数。首先,如果输入的数是负数,那么将其转换为补码形式。然后,不断地将数除以16,并将余数映射到十六进制字符上,直到商为0。最后,将得到的字符序列逆序拼接起来即为结果。

时间复杂度: O(1)

空间复杂度: O(1)

class Solution:
    def toHex(self, num: int) -> str:
        # 如果是负数则转化成补码
        if num < 0:
            num += 2 ** 32
        
        stack = []  # 用于存储十六进制字符
        s = '0123456789abcdef'  # 十六进制字符映射表
        
        # 不断除以16取余数,直到商为0
        while num:
            stack.append(s[num % 16])
            num //= 16
        
        # 如果栈为空,说明输入为0
        if not stack:
            return '0'
        
        # 将栈中的字符逆序拼接起来形成最终结果
        stack.reverse()
        return ''.join(stack)

Explore

是的,这个方法适用于所有的32位整数。在32位整数中,最小的整数是 -2^31。当加上 2^32 时,它变成了 2^32 - 2^31,即 2^31。这是因为在32位整数的存储中,最高位是符号位。一旦这个数转换为补码形式,它就变成了一个正数,可以正常使用十六进制转换的方法处理。

在循环开始之前,如果数字是负的,算法已经通过加上 2^32 转换成了补码形式,这会把负数转换为对应的正数。因此,当进入循环时,数字已经是非负数,所以不需要在循环中再考虑数字为负的情况。这保证了循环中 `num` 总是非负的,正确地结束循环。

这种情况只适用于输入数字为0的情况。因为只有当输入的数字是0时,循环体内的代码不会执行(0除以16的余数仍然是0),因此栈不会有任何元素被添加。如果输入的数字不是0,在数学运算中总会至少有一次余数不为0的情况,这将导致至少有一个字符被添加到栈中。

这种方法在处理接近32位整数最大或最小值的数字时效率仍然是可接受的。尽管数字大,但是在转换成补码后,仍然是一个有限的32位整数。算法的时间复杂度主要取决于数字的位数,因此最多需要处理32次迭代(除以16并取余数),这保持了算法的效率。