leetcode
leetcode 351 ~ 400
数字转换为十六进制数

数字转换为十六进制数

难度:

标签:

题目描述

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

注意:

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

示例 1:

输入:
26

输出:
"1a"

示例 2:

输入:
-1

输出:
"ffffffff"

代码结果

运行时间: 20 ms, 内存: 0.0 MB


/*
 * 题目思路:
 * 1. 使用字符数组存储十六进制字符'0'到'f'。
 * 2. 特殊处理数字为0的情况。
 * 3. 对负数进行补码运算。
 * 4. 使用流的方式处理每一位的转换,最后拼接成字符串。
 */
import java.util.stream.Collectors;
import java.util.stream.IntStream;
 
public class Solution {
    public String toHex(int num) {
        if (num == 0) return "0";
        char[] hexChars = "0123456789abcdef".toCharArray();
        StringBuilder hexString = new StringBuilder();
        int n = num;
        while (n != 0) {
            int index = n & 0xF;
            hexString.append(hexChars[index]);
            n >>>= 4;
        }
        return hexString.reverse().toString();
    }
}

解释

方法:

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

时间复杂度:

O(1)

空间复杂度:

O(1)

代码细节讲解

🦆
在算法中,对于负数的处理是通过加上 2^32 来转换为补码,这个方法是否适用于所有的32位整数,包括极端情况比如最小的整数 -2^31?
是的,这个方法适用于所有的32位整数。在32位整数中,最小的整数是 -2^31。当加上 2^32 时,它变成了 2^32 - 2^31,即 2^31。这是因为在32位整数的存储中,最高位是符号位。一旦这个数转换为补码形式,它就变成了一个正数,可以正常使用十六进制转换的方法处理。
🦆
题解中提到的方法是通过循环除以16并取余数来转化为十六进制,那么在循环条件为 `while num` 时,为什么不需要考虑数字为负的情况?
在循环开始之前,如果数字是负的,算法已经通过加上 2^32 转换成了补码形式,这会把负数转换为对应的正数。因此,当进入循环时,数字已经是非负数,所以不需要在循环中再考虑数字为负的情况。这保证了循环中 `num` 总是非负的,正确地结束循环。
🦆
题解提到,如果栈为空则直接返回 '0',这种情况是否只适用于输入数字为0的情况,还是还有其他可能性?
这种情况只适用于输入数字为0的情况。因为只有当输入的数字是0时,循环体内的代码不会执行(0除以16的余数仍然是0),因此栈不会有任何元素被添加。如果输入的数字不是0,在数学运算中总会至少有一次余数不为0的情况,这将导致至少有一个字符被添加到栈中。
🦆
算法通过将数字不断除以16并取余数计算十六进制数,那么在数字非常大(接近32位整数的最大值)或非常小(接近32位整数的最小值)的情况下,这种方法的效率如何?
这种方法在处理接近32位整数最大或最小值的数字时效率仍然是可接受的。尽管数字大,但是在转换成补码后,仍然是一个有限的32位整数。算法的时间复杂度主要取决于数字的位数,因此最多需要处理32次迭代(除以16并取余数),这保持了算法的效率。

相关问题