[蓝桥杯]十六进制转八进制

题目:

问题描述
  给定n个十六进制正整数,输出它们对应的八进制数。

输入格式
  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由0~9、大写字母A~F组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。

输出格式
  输出n行,每行为输入对应的八进制正整数。

  【注意
  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。

样例输入
  2
  39
  123ABC

样例输出
  71
  4435274

  提示
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。



   看似不难,的确不难。但是我提交了7次都不是满分,后来下了他的样例看了一下,居然是10万位的16进制,转换成2进制即40万位数据,只能当做字符串来处理了,看下之前写的:

import java.util.*;
public class Main {
	static Dictionary<String, String> dic=new Hashtable<String, String>();
	static Dictionary<String, String> dic2=new Hashtable<String, String>();
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int n=scanner.nextInt();
		dic.put("0", "0000");
		dic.put("1", "0001");
		dic.put("2", "0010");
		dic.put("3", "0011");
		dic.put("4", "0100");
		dic.put("5", "0101");
		dic.put("6", "0110");
		dic.put("7", "0111");
		dic.put("8", "1000");
		dic.put("9", "1001");
		dic.put("A", "1010");
		dic.put("B", "1011");
		dic.put("C", "1100");
		dic.put("D", "1101");
		dic.put("E", "1110");
		dic.put("F", "1111");
		dic2.put("001", "1");
		dic2.put("010", "2");
		dic2.put("011", "3");
		dic2.put("100", "4");
		dic2.put("101", "5");
		dic2.put("110", "6");
		dic2.put("111", "7");
		dic2.put("000", "0");
		for (int i = 0; i < n; i++) {
			StringBuilder builder=new StringBuilder(scanner.next());
			fun(builder);
		}
	}

	private static void fun(StringBuilder string) {
		// TODO Auto-generated method stub
		StringBuilder s=new StringBuilder();
		for (int i = 0; i < string.length(); i++) {
			s.append(dic.get(string.charAt(0)+""));
		}
		fun2(s);
	}

	private static void fun2(StringBuilder s) {
		// TODO Auto-generated method stub
		if(s.length()%3==1)
		{
			s.insert(0, "00");
		}
		else if(s.length()%3==2)
		{
			s.insert(0, "0");
		}
		StringBuilder builder=new StringBuilder();
		for (int i = s.length()-1; i > 0; i-=3) {
			String temp=s.charAt(i-2)+""+s.charAt(i-1)+""+s.charAt(i);
			builder.insert(0, dic2.get(temp));
		}
		if(builder.charAt(0)=='0')
		{
			builder=builder.deleteCharAt(0);
		}
		System.out.println(builder);
	}

}


通过查字典来对转换过来的2进制进行处理,这里用如果不用stringBuilder用string的话 效率非常低,但是这样写还是超时,大概2秒-3秒之间出结果,但是还是慢了,没办法 只有改进。

正确代码:

import java.util.*;
public class Main {
	static Dictionary<String, String> dic=new Hashtable<String, String>();//16进制转2进制对应字典
	static Dictionary<String, String> dic2=new Hashtable<String, String>();//2进制转8进制对应字典
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int n=scanner.nextInt();
		dic.put("0", "0000");
		dic.put("1", "0001");
		dic.put("2", "0010");
		dic.put("3", "0011");
		dic.put("4", "0100");
		dic.put("5", "0101");
		dic.put("6", "0110");
		dic.put("7", "0111");
		dic.put("8", "1000");
		dic.put("9", "1001");
		dic.put("A", "1010");
		dic.put("B", "1011");
		dic.put("C", "1100");
		dic.put("D", "1101");
		dic.put("E", "1110");
		dic.put("F", "1111");
		dic2.put("001", "1");
		dic2.put("010", "2");
		dic2.put("011", "3");
		dic2.put("100", "4");
		dic2.put("101", "5");
		dic2.put("110", "6");
		dic2.put("111", "7");
		dic2.put("000", "0");//字典数据添加
		for (int i = 0; i < n; i++) {//n个16进制
			StringBuilder builder=new StringBuilder(scanner.next());
			fun(builder);
		}
	}

	private static void fun(StringBuilder string) {
		// TODO Auto-generated method stub
		StringBuilder s=new StringBuilder();
		for (int i = 0; i < string.length(); i++) {
			s.append(dic.get(string.charAt(i)+""));
		}
		fun2(s);//把转换过来的二进制进行处理

	}

	private static void fun2(StringBuilder s) {
		// TODO Auto-generated method stub
		if(s.length()%3==1)//不足3位补0
		{
			s.insert(0, "00");
		}
		else if(s.length()%3==2)
		{
			s.insert(0, "0");
		}
		for (int i = 0; i < s.length(); i+=3) {
			String temp=s.charAt(i)+""+s.charAt(i+1)+""+s.charAt(i+2);
			if(i==0&&temp.equals("000"))//通过字典找到对应8进制输出
				continue;
			System.out.print(dic2.get(temp));
		}
		System.out.println();
	}

}
直接输出才是正解。


原理:将2进制作为中间进制,这里用stringbuilder进制尾部追加(切记数据大了勿用string),4个二进制=一个16进制,3个二进制=一个八进制,不足3位向前补0,转换过来的2进制通过字典查询对应8进制直接输出即可。


网上也有写这个题目的,方法也很好,不过我看着并不是很明白。。。。。。。。。


如各位觉得能优化的地方欢迎共同进步。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值