持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
题目
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。
注意:
- 十六进制中所有字母(
a-f)都必须是小写。 - 十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符
'0'来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。 - 给定的数确保在32位有符号整数范围内。
示例 1:
- 输入:
26- 输出:
"1a"
示例 2:
- 输入:
-1- 输出:
"ffffffff"
方法一:位运算
思路及解法
题目要求将给定的整数 转换为十六进制数,负整数使用补码运算方法。
在补码运算中,最高位表示符号位,符号位是 表示正整数和零,符号位是 表示负整数。 位有符号整数的二进制数有 位,由于一位十六进制数对应四位二进制数,因此 位有符号整数的十六进制数有 位。将 的二进制数按照四位一组分成 组,依次将每一组转换为对应的十六进制数,即可得到 的十六进制数。
假设二进制数的 组从低位到高位依次是第 组到第 组,则对于第 组,可以通过 得到该组的值,其取值范围是 到 (即十六进制的 )。将每一组的值转换为十六进制数的做法如下:
- 对于 到 ,数字本身就是十六进制数;
- 对于 到 ,将其转换为 到 中的对应字母。
对于负整数,由于最高位一定不是 ,因此不会出现前导零。对于零和正整数,可能出现前导零。避免前导零的做法如下:
- 如果 ,则直接返回 ;
- 如果 ,则在遍历每一组的值时,从第一个不是 的值开始拼接成十六进制数。
代码
class Solution {
func toHex(_ num: Int) -> String {
if 0 == num {
return "0"
}
var sb: String = ""
var i: Int = 7
while i >= 0 {
let val: Int = (num >> (i * 4)) & 0xf
if sb.count > 0 || val > 0 {
let digit: String = val < 10 ? String(val) : String(Character(UnicodeScalar(Int(Character("a").asciiValue!) + val - 10)!))
sb += digit
}
i -= 1
}
return sb
}
}
复杂度分析
-
时间复杂度:,其中 是整数的十六进制数的位数,这道题中 。无论 的值是多少,都需要遍历 的十六进制表示的全部数位。
-
空间复杂度:,其中 是整数的十六进制数的位数,这道题中 。空间复杂度主要取决于中间结果的存储空间,这道题中需要存储 的十六进制表示中的除了前导零以外的全部数位。