。。。。十六进制转八进制,转的我的心都累了,自己用了两种方法,结果都是运行超时,哎!最后迫不得已还是借鉴了度娘的代码,在这三次编码中还是学到了很多知识。
方法一:
转换思路:以前学《大学计算机》时,在进制转化这块就学了书上的方法,十六进制转为八进制,十六进制---->十进制----->八进制。于是就按照这个来编码了
编码思路:
十六进制----->十进制:一般的操作方法,就是将十六进制的每一位分别乘以16的多少次方,然后相加。那在计算机中,将十六进制的每一位截取出来,然后判断得到的字符是不是ABCDEF,(我竟然还用了正则表达式),如果是就将他们的ASCALL码值减去55,这样可以得到在十六进制中相应的值,然后再用循环分别得到要乘的16的多少次方。定义一个变量将所有得到值相加。
十进制---->八进制:除k取余,定义remainder来存放余数,quotient来存放商,用一个字符串或者字符数组将所有余数存放起来,当quotient为0时,将字符串逆序输出。
代码实现:
import java.util.Scanner;
public class Mian_sixteentoeight {
//十六进制转化为十进制
public int sixteemtoten(String num) {
int len=num.length();
int sum=0;
for(int i=0;i<len;i++) { //对十六进制的每一个数进行操作
int number;
int j=i;
char a=num.charAt(len-i-1);
if(65<=a&&a<=70) { //判断a是否是ABCDEF中的第一
number=(int)a-55;
}else {
number=(int)a-48;
}
//这里是为了实现乘以16的多少次方
while(j>0) {
number=number*16; //时间复杂度是n^2
j--;
}
sum=sum+number; //将所有的结果相加
}
return sum;
}
//十进制转化为八进制
public String tentoeight(int num) {
int remainder=num%8;
int quotient=num/8;
String eight =""; // 实现逆序输出
while(quotient!=0) {
//将int型拼接到String上的三种方法
eight=eight+remainder; //字符拼接
remainder=quotient%8;
quotient=quotient/8;
}
eight=eight+remainder;
//对字符串进行反转
char[] str=eight.toCharArray();
eight="";
for(int i=str.length-1;i>=0;i--) {
eight=eight+str[i]; //所以不管是字符串加char还是加int 就直接相加就可以了 这里的时间复杂度也是n^2
}
return eight;
}
public static void main(String[] args) {
Mian_sixteentoeight change=new Mian_sixteentoeight();
Scanner scanner=new Scanner(System.in);
int n=Integer.parseInt(scanner.nextLine()); //必须是next Line这样下面的收录数据才不会错
String[] sixnum=new String[n];
for(int i=0;i<n;i++) {
sixnum[i]=scanner.nextLine();
}
for(int i=0;i<n;i++) {
int result=change.sixteemtoten(sixnum[i]);
System.out.println(result);
String str=change.tentoeight(result);
System.out.println(str);
}
}
}
上面代码就是我具体实现过程,
在编上面这一段代码我学到的知识:
- 1.我如果想直接在main函数里面调用函数,可以将函数定义为static ,这样就不用每次创建对象了,然后用对象调用。
- 2.Java中的正则表达式,String reg=“正则表达式内容” 例:reg="[A-Z]" ,匹配: 字符串.matches(reg)。
- 3.将char转化为String的方法 String str=String.valueOf(a) a是字符
- 4.两种将String转换为int型的方法
int n=Integer.parseInt(字符串);
int n=Integer.valueOf(字符串).intValue(); - 5.将int类型的数拼接到字符串上的三种方法: 字符串不管是和int类型还是char 直接相加就可以实现拼接。
eight=eight+String.valueOf(remainder)
eight=eight.concat(String.valueOf(remainder));
eight=eight+remainder;
方法二
将上面的代码拿到测评系统去,结果运行超时。。。。好没办法执行方法二。
转换思路:十六进制----->二进制----->八进制, 这个方法应该就是我在课本上没有学到的简便方法了。
编码思路:四位二进制数表示一个十六进制数,三位二进制数表示一个八进制数,秉承着这样的思想,我弄了两个map集合来存放这样的对应关系,同时写了两个方法来获取对应key的value值,(也可以不用),转换过程都还是挺简单的,中间部分,因为要转为八进制,而三位二进制为一个八进制,所以需要添加0。
代码实现:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main_sixteentoeight01 {
private Map<Character,String> sixtotwo=new HashMap<Character,String>();
private Map <String,Character> twotoeight=new HashMap<String,Character>();
public Main_sixteentoeight01() {
sixtotwo.put('0', "0000");
sixtotwo.put('1', "0001");
sixtotwo.put('2', "0010");
sixtotwo.put('3', "0011");
sixtotwo.put('4', "0100");
sixtotwo.put('5', "0101");
sixtotwo.put('6', "0110");
sixtotwo.put('7', "0111");
sixtotwo.put('8', "1000");
sixtotwo.put('9', "1001");
sixtotwo.put('A', "1010");
sixtotwo.put('B', "1011");
sixtotwo.put('C', "1100");
sixtotwo.put('D', "1101");
sixtotwo.put('E', "1110");
sixtotwo.put('F', "1111");
twotoeight.put("000",'0');
twotoeight.put("001",'1');
twotoeight.put("010",'2');
twotoeight.put("011",'3');
twotoeight.put("100",'4');
twotoeight.put("101",'5');
twotoeight.put("110",'6');
twotoeight.put("111",'7');
}
public String getTwo(Character six) {
return sixtotwo.get(six);
}
public Character getEight(String two) {
return twotoeight.get(two);
}
public void transform(String num) {
//完成到二进制的转化
int num_len=num.length();
String temp=""; //这里应该用String Builder的
for(int i=0;i<num_len;i++) {
char a=num.charAt(i);
temp=temp+getTwo(a);
}
//将二进制转化为八进制
int rest=temp.length()%3;
while(rest<3&&rest!=0) { //添加0
temp='0'+temp;
rest++;
}
if(temp.substring(0,3).equals("000")) { //判断前三位是否为0,这是为了不出现前导0的情况
temp=temp.substring(3);
}
int len=temp.length();
for(int i=0;i<len;i=i+3) { //实现到八进制的转换,并且直接输出结果
String str=temp.substring(i,i+3);
System.out.print(getEight(str));
}
}
public static void main(String[] args) {
Main_sixteentoeight01 change=new Main_sixteentoeight01();
Scanner scanner=new Scanner(System.in);
int n=Integer.parseInt(scanner.nextLine()); //必须是next Line这样下面的收录数据才不会错
String[] sixnum=new String[n];
for(int i=0;i<n;i++) {
sixnum[i]=scanner.nextLine();
}
for(int i=0;i<n;i++) {
change.transform(sixnum[i]);
System.out.println();
}
}
}
以上就是代码实现过程,相对来说操作代码行就少多了。我以为可以通过测评系统了,结果还是超时。。。。。
方法三:
基于上两种方法都超时了,我不得不求助度娘了,看看大佬们的代码
转换思路:和方法二的转换思路是一样的。
编码思路:在十六进制转二进制时,没有用map集合来实现对应的转化关系,而是用switch case(这样可以节省系统空间),在二进制转八进制时,采用了特殊的算法(可能只是我不知道吧) a=(str2.charAt(i)-‘0’)*4+(str2.charAt(i+1)-‘0’)*2+(str2.charAt(i+2)-‘0’);
代码实现:
import java.util.Scanner;
public class Main_sixteentoeight02 {
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
String[] st=new String[n];
for(int i=0;i<n;i++)
{
st[i] =sc.next();
}
sc.close();
for(int i=0;i<n;i++)
{
String str1=ttos(st[i]);
//补全二进制数 这样就好操作 因为后面要进行三个三个来 同时要去掉前导0
int len_str1=str1.length();
if(len_str1%3==1)str1="00"+str1;
else if(len_str1%3==2)str1="0"+str1; //else if 里面可以没有else呢
ttoe(str1);
}
}
public static String ttos(String str)
{
int len_str=str.length();
StringBuilder str2=new StringBuilder(); //因为要对字符串进行多次操作 所以我们用StringBuilder
for(int i=0;i<len_str;++i)
{
switch(str.charAt(i))
{
case '0':str2.append("0000");break;
case '1':str2.append("0001");break;
case '2':str2.append("0010");break;
case '3':str2.append("0011");break;
case '4':str2.append("0100");break;
case '5':str2.append("0101");break;
case '6':str2.append("0110");break;
case '7':str2.append("0111");break;
case '8':str2.append("1000");break;
case '9':str2.append("1001");break;
case 'A':str2.append("1010");break;
case 'B':str2.append("1011");break;
case 'C':str2.append("1100");break;
case 'D':str2.append("1101");break;
case 'E':str2.append("1110");break;
case 'F':str2.append("1111");break;
default:break;
}
} return str2.toString();
}
public static void ttoe(String str2)
{
int len=str2.length();
int a;
a=(str2.charAt(0)-'0')*4+(str2.charAt(1)-'0')*2+(str2.charAt(2)-'0'); //为了不出现前导0
if(a!=0)
System.out.print(a); //若a!=0就直接输出了
for(int i=3;i<=len-2;i+=3)
{
a=(str2.charAt(i)-'0')*4+(str2.charAt(i+1)-'0')*2+(str2.charAt(i+2)-'0');
System.out.print(a);
}
System.out.println();
}
}
上面就是代码,哎,还是大佬们厉害,终于通过了
学到的知识:
- 1.将方法定义为static 这样在main方法中调用的时候就直接调用即可
- 2.输入流要关闭
- 3.十六进制转化为二进制 不需要用一个集合来存放 就直接switch case 这样可以节约空间
- 4.十六进制转二进制时 因为对字符是要进行拼接操作 根据十六进制的位数对字符串的操作次数就较多 所以这里我们用的是StringBuiler, 节约空间
- 5.二进制转八进制的特殊处理方法 需要学会呢