Given an integer num
, convert it to its hexadecimal representation as a string and return it. The hexadecimal representation should use lowercase letters ('a'
to 'f'
) for digits greater than 9. For negative numbers, use two's complement hexadecimal representation for 32-bit integers.
-231 ≤ num ≤ 231 - 1
).The problem asks for a manual conversion of an integer to its hexadecimal string, similar to how you might convert decimal to binary by repeatedly dividing by 2. Here, we divide by 16 and map the remainders to hexadecimal digits. For negative numbers, we must represent them as 32-bit unsigned values using two's complement, which means masking the number to get its correct bitwise representation.
A brute-force approach would be to use built-in formatting, but the problem restricts us from doing so. Instead, we need to handle the conversion ourselves, including edge cases like zero and negative numbers. Optimization isn't a major concern here since the conversion is straightforward, but we must be careful with bit manipulation for negative numbers.
num
is zero, return "0" immediately.num
is negative, convert it to its 32-bit unsigned equivalent by masking with 0xFFFFFFFF
.num
is not zero, repeatedly:num
divided by 16.num
by 16 (using integer division).This approach ensures we handle both positive and negative numbers, avoid leading zeros, and do not use forbidden built-in functions.
Let's walk through the conversion of num = -26
:
num
is negative, convert to 32-bit unsigned: num = -26 & 0xFFFFFFFF = 4294967270
.4294967270 % 16 = 10
('a'), 4294967270 // 16 = 268435454
.268435454 % 16 = 14
('e'), 268435454 // 16 = 16777215
.16777215 % 16 = 15
('f'), 16777215 // 16 = 1048575
.num
becomes zero, collecting digits: ['a', 'e', 'f', 'f', 'f', 'f', 'f', 'f'] (in reverse).
Thus, -26
is represented as "ffffffe6"
in hexadecimal (32-bit two's complement).
To convert an integer to its hexadecimal string, we repeatedly divide by 16 and map remainders to hex digits, handling negative numbers using 32-bit two's complement. This approach is efficient, simple, and avoids forbidden built-ins, making it both robust and elegant. The key insight is using bit masking for negatives and building the result in reverse.
class Solution:
def toHex(self, num: int) -> str:
if num == 0:
return "0"
hex_chars = "0123456789abcdef"
result = []
# Handle negative numbers using two's complement
num &= 0xFFFFFFFF
while num:
result.append(hex_chars[num % 16])
num //= 16
return ''.join(reversed(result))
class Solution {
public:
string toHex(int num) {
if (num == 0) return "0";
string hex_chars = "0123456789abcdef";
string result = "";
unsigned int n = num;
while (n) {
result += hex_chars[n % 16];
n /= 16;
}
reverse(result.begin(), result.end());
return result;
}
};
class Solution {
public String toHex(int num) {
if (num == 0) return "0";
char[] hexChars = "0123456789abcdef".toCharArray();
StringBuilder sb = new StringBuilder();
// Use unsigned right shift to handle negatives
while (num != 0 && sb.length() < 8) {
sb.append(hexChars[num & 0xf]);
num >>>= 4;
}
return sb.reverse().toString();
}
}
var toHex = function(num) {
if (num === 0) return "0";
let hexChars = "0123456789abcdef";
let result = "";
// Use 32-bit unsigned representation
num = num >>> 0;
while (num) {
result = hexChars[num % 16] + result;
num = Math.floor(num / 16);
}
return result;
};