概述
蓝桥杯——十六进制转八进制
- 0.前言
- 1.解题过程
- 1.1原题
- 1.1.1问题描述
- 1.1.2输入格式
- 1.1.3输出格式
- 1.2代码
- 1.2.1常规做法
- 1.2.2非常规做法(我自己的方法)
- 1.2.2.1方案概要
- 1.2.2.2细节问题
- 1.2.2.3代码
- 1.2.2.4说明
- 2.总结
0.前言
这道题乍一看不难,无非就是调用Long.valueOf(n,16);
和Integer.toString(n, 8)
,先转成十进制再转成八进制。但仔细看条件会发现数值非常大,这种方法是不行的。
1.解题过程
1.1原题
1.1.1问题描述
给定n个十六进制正整数,输出它们对应的八进制数。
1.1.2输入格式
输入的第一行为一个正整数n (1<=n<=10)。
接下来n行,每行一个由09、大写字母AF组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
1.1.3输出格式
输出n行,每行为输入对应的八进制正整数。
说明:输入的十六进制数不会有前导0,比如012A,输出的八进制数也不能有前导0。 |
---|
1.2代码
1.2.1常规做法
思路就是寻找一个能表示很大数值范围的类来表示,BigInteger
正好符合
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] agrs) {
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
String[] arr=new String[n];
String[] brr=new String[n];
for (int i = 0; i < arr.length; i++) {
arr[i]=sc.next();
//调用自带的BigInteger()类表示,需要熟练掌握Java的常用API
brr[i]=new BigInteger(arr[i],16).toString(8);
}
for (int i = 0; i < brr.length; i++) {
System.out.println(brr[i]);
}
sc.close();
}
}
1.2.2非常规做法(我自己的方法)
最开始我的想法也是找一个能表示的类,但最后没找到,而且看了那么长的字符串之后,感觉就不是让我们直接用,可能是找别的方法。
我的思路是这样,在上课的时候,我们经常把16进制转化为2进制,只需要按位展开,而把2进制转化为16进制只需要每四位转化为16进制拼接即可,那么我就可以把这么长的数字转化为字符串,然后把字符串转化为2进制,再把2进制的字符串每三位为一组转化为8进制的字符串。
1.2.2.1方案概要
确定了思路之后,我们需要考虑几个问题,第一个就是映射的问题,把16进制映射为四位的2进制数字,可以考虑用一个HashMap
存储,键为十六进制的0-F,值为二进制的0000-1111。把2进制映射为8进制也是一样的思路,新建一个HashMap
,键为二进制的000-111,值为八进制的0-7。遇到key时,直接替换为对应的value。
1.2.2.2细节问题
确定方案之后,还有几个问题需要考虑,第一个就是前导0的问题,如果十六进制下第一位是1,转化为二进制是0001,转化为八进制是001,这样的话,前面两位0不应该存在。需要考虑去除前面多余的0,第二个是,如果二进制的字符串总共有两位,比如11,那么按照建立的HashMap
来看就找不到映射,需要考虑这种情况。
1.2.2.3代码
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] agrs) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
//存储输入的十六进制字符串
String[] arrStrings = new String[n];
//遍历赋值
for (int i = 0; i < n; i++) {
arrStrings[i] = sc.next();
}
//十六进制转二进制的映射表
Map<String, String> x2bMap = new HashMap<>(16);
//二进制转八进制的映射表
Map<String, String> b2oMap = new HashMap<>(8);
//二进制字符串,StringBuilder做拼接的时候速度比较快
StringBuilder binaryNumBuilder = new StringBuilder();
//最终的八进制结果字符串
StringBuilder resultBuilder = new StringBuilder();
//键
String key;
//值
String value;
//局部结果的字符串
String partString;
//十六进制转二进制映射表赋值
for (int i = 0; i < 16; i++) {
key = String.format("%x", i).toUpperCase();
value = String.format("%04d", Integer.parseInt(Integer.toBinaryString(i)));
x2bMap.put(key, value);
}
//二进制转八进制映射表赋值
for (int i = 0; i < 8; i++) {
key = String.format("%03d", Integer.parseInt(Integer.toBinaryString(i)));
value = String.valueOf(i);
b2oMap.put(key, value);
}
for (String string : arrStrings) {
//转化为二进制字符串
for (int i = 0; i < string.length(); i++) {
key = String.valueOf(string.charAt(i));
value = x2bMap.getOrDefault(key, "-1");
binaryNumBuilder.append(value);
}
//考虑如果前面几位为0时候,去除0
if (binaryNumBuilder.charAt(0)=='0'){
for (int i = 1; i < 4; i++) {
if (binaryNumBuilder.charAt(i) == '1') {
binaryNumBuilder = new StringBuilder(binaryNumBuilder.substring(i));
break;
}
}
}
//二进制转八进制,从后往前,每次-3
for (int i = binaryNumBuilder.length(); i > 0; i -= 3) {
//如果最后字符串长度小于3,需要单独处理
if (i < 3) {
partString = binaryNumBuilder.substring(0, i);
partString = String.format("%o", Integer.valueOf(partString, 2));
} else {
partString = binaryNumBuilder.substring(i - 3, i);
partString = b2oMap.get(partString);
}
resultBuilder.append(partString);
}
//此时拼接的字符串是正确结果的倒置,需要倒置后输出
System.out.println(resultBuilder.reverse().toString());
//清空,重新赋值
binaryNumBuilder = new StringBuilder();
resultBuilder = new StringBuilder();
}
sc.close();
}
}
1.2.2.4说明
代码如上,关键地方都有相应的注释说明,这个方法相对于常规做法复杂了不少,但很锻炼思维。这种模拟计算机进行计算的题目有很多,虽然一个两个可以使用常规做法,但不绝对。掌握这种思想,对之后的练习也有好处。这种方法的时间复杂度和空间复杂度相对于常规做法要小不少,也算是一个成就吧。对比如下。
- 非常规做法:
- 常规做法:
2.总结
这道题,我做了很久,后来自己查了一下,发现还有那么简单的常规做法,后来我想明白了基础练习的题目,大多都可以直接做,不需要考虑那么复杂。但考虑复杂,对自己代码能力和思维的严谨性有很大的提高。
最后
以上就是自信发箍为你收集整理的蓝桥杯——十六进制转八进制0.前言1.解题过程2.总结的全部内容,希望文章能够帮你解决蓝桥杯——十六进制转八进制0.前言1.解题过程2.总结所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复