[Mnsx_x]刷题笔记——数字转化为十六进制数
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。
注意:
1.十六进制中所有字母(a-f)都必须是小写。
2.十六进制字符串中不能包含多余的前导零。如果要转化的数为0,那么以单个字符’0’来表示;对于其他情况,十六进制字符串中的第一个字符将不会是0字符。
4.给定的数确保在32位有符号整数范围内。
5.不能使用任何由库提供的将数字直接转换或格式化为十六进制的方法。
题目解析
阅读题目可知,题目主要目的是将十进制的整型数据转化为十六进制的数,第一次阅读后可以看出能够通过将最高位往后的数分别求出,大于等于十的数转换为字符,通过StringBuffer装载,再通过reverse()函数反转输出。
问题解决
第一次完成此题时遇到的问题在于不懂得如何处理负数,借鉴了三叶大佬的算法,使用2的32次方加上这个数来代替反码(需要使用long型装载)。
参考文献
思路一——模拟 + 进制转换
通过数学的思路,对十进制数进行求余,第一次求出的值为最高位依次往后,求余后再对其进行求余直到等于零位置,通过StringBuffer装载,再通过reverse反转。
补码——如果正数不变,如果为负数取反加一
那么这道题中模拟补码的执行,在负数上加上2的32次方即可。
class Solution {
public String toHex(int num) {
//为零直接返回0
if(num == 0){
return "0";
}
//使用long型装载负数的反码
long lNum = num;
if(num < 0){
lNum = (long)(Math.pow(2, 32) + num);
}
//实例化StringBuffer来装载所得字符
StringBuffer sb = new StringBuffer();
//循环,数据对16求余,所得为从最高位开始往后的字符,如果为大于等于10的数将转换为a-e的字符,添加到StringBuffer中,再对数据求除,直到等于零停止循环
while(lNum != 0){
long x = lNum % 16;
char ch = (char)(x + '0');
if(x >= 10){
ch = (char)('a' + (x - 10));
}
sb.append(ch);
lNum /= 16;
}
//通过reverse()反转输出
return sb.reverse().toString();
}
}
时间复杂度:O(8) 因为十六进制为8位
空间复杂度:O(8) 因为十六进制为8位
思路二——模拟 + 分组换算
完成题目后参考题解总结,可以将数据看成二进制数,二进制数int型位32位,而十六进制为8位,可以二进制的数据分为四个数一组,得出的数即为十六进制数每位上的结果,二进制的1111为15,那么使用输入数据&15即可得出十六进制上从高到低位上的数,再将数据>>>无符号右移4位即可四个数组合处理,最后reverse()反转输出。
class Solution {
public String toHex(int num) {
//若为零直接返回
if(num == 0){
return "0";
}
//实例化StringBuffer
StringBuffer sb = new StringBuffer();
//循环,四个数处理一起处理,使用&来保留指定位数的数(如15[1111]则是保留前四位)再通过>>>来四位组合处理
while(num != 0){
int x = num & 15;
char ch = (char)(x + '0');
if(x >= 10){
ch = (char)('a' + (x - 10));
}
sb.append(ch);
num >>>= 4;
}
//反转输出
return sb.reverse().toString();
}
}
时间复杂度:O(8) 因为十六进制为8位
空间复杂度:O(8) 因为十六进制为8位
总结
鉴于对于位运算的不熟悉,将专门对于位运算进行整理