蓝桥杯 16进制转换8进制

蓝桥杯 16进制转换8进制

我表示我自己太渣渣了,总是超时,通不过测试。

题目

问题描述
  给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
  输入的第一行为一个正整数n (1<=n<=10)。
  接下来n行,每行一个由09、大写字母AF组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
  输出n行,每行为输入对应的八进制正整数。
注意
  输入的十六进制数不会有前导0,比如012A。
  输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
提示
  先将十六进制数转换成某进制数,再由某进制数转换成八进制。

思路

刚开始没有什么思路,就用最原始的做法,先将16进制转换为10进制,然后再由10进制转换为8进制,结果错误。下载测试的数据,才发现数据时如此变态,变换成BigInteger来存储数据,结果运行超时,思考后,发现按照传统的方式,是无法通过的,迫不得已上网找答案,找进制转换的技巧。

进制转换基础,进制转换可知,可以将16进制转换为2进制,再由2进制进行转化8进制,至于为什么这样做呢,因为16进制每一个位子上的数字都可以变成4位的2进制数,而每3个二进制数又可以组成8进制上对应位子的数字

再通过数电逻辑上计算2进制的方法:8421法,对应有1的位置加上对应的数字,结果应该就可以出来了。而我按照思路编写之后,还是运行超时。到底哪里出错,看到参考通过的例子后,我才发现,自己的算法确实不够优化

测试数据

变态的测试数据

16转10,10转8

/*
     * 这种是16进制转化成10进制,然后再转化成8进制 超时,
     */
    public void convert16from10to8(String num16) {
        int flag = 0;
        BigInteger sum = new BigInteger("0");
        BigInteger tmp = new BigInteger("16");
        // 16先转换成10进制
        char[] chArr = num16.toCharArray();
        for (int x = chArr.length - 1; x >= 0; x--) {
            switch (chArr[x]) {
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'F':
                // sum += (chArr[x] - '0'-7) * Math.pow(16, flag++);
                sum = sum.add(tmp.pow(flag++).multiply(
                        new BigInteger((chArr[x] - '0' - 7) + "")));
                break;
            default:
                // sum += (chArr[x] - '0') * Math.pow(16, flag++);
                sum = sum.add(tmp.pow(flag++).multiply(
                        new BigInteger((chArr[x] - '0') + "")));
                break;
            }
        }
        System.out.println(sum);
        StringBuffer sb = new StringBuffer();
        while (sum.intValue() > 8) {
            // sb.append(sum%8);
            sb.insert(0, sum.remainder(new BigInteger("8")));
            sum = sum.divide(new BigInteger("8"));
        }
        sb.insert(0, sum);
        // sb.append(sum);
        System.out.println(sb.toString());
    }

16转2,2转8

    /*
     * 16进制转成2进制,再转8进制 16--》2 每个位上的数字都可以转化为4个位的2进制
     * 每三个为上的2进制组合转化为8进制上的每个位上的数字,不够就补0
     */
    public void convert16from2to8(String num16) {
        char[] chArr = num16.toCharArray();
        int tmp = 0;
        StringBuffer sbSum = new StringBuffer();
        for (int x = 0; x < chArr.length; x++) {
            switch (chArr[x]) {// 字符对应的整数
            case 'A':
            case 'B':
            case 'C':
            case 'D':
            case 'E':
            case 'F':
                tmp = chArr[x] - '0' - 7;
                break;
            default:
                tmp = chArr[x] - '0';
                break;

            }
            StringBuffer sb = new StringBuffer();
            // 转化为二进制
            while (tmp >= 2) {
                sb.insert(0, tmp % 2);
                tmp /= 2;
            }
            sb.insert(0, tmp);
            // System.out.println(sb.length());
            int len = 4 - sb.length();// 假如直接写在for循环里面sb在变化,导致len会变化
            for (int y = 0; y < len; y++)
                sb.insert(0, 0);
            // System.out.println(sb.toString());
            sbSum.append(sb);
        }
        
//      System.out.println(sbSum.toString());
        StringBuffer sbSum8=new StringBuffer();//记录最终的结果
        int tmp8item=0;
        // 每3个一组,不够尽兴高位补0,即最左边补0,采用421,
        // 或者用一个3做循环,进行划分区域,有1,就根据421的方式进行相加
        char[] chArr2 = sbSum.toString().toCharArray();
        //1001
        for (int z = chArr2.length - 1, num3 = 0; z >= 0; z--) {
            if (chArr2[z] - '0' == 1) {
                switch (num3) {
                case 0:
                    tmp8item+=1;
                    break;
                case 1:
                    tmp8item+=2;
                    break;
                case 2:
                    tmp8item+=4;
                    break;
                }
            }
            if((num3+1)%3==0){
                sbSum8.insert(0, tmp8item);
                tmp8item=0;
            }
            num3=(num3+1)%3;
        }
        if(sbSum8.substring(0, 1).equals("0"))//输出的八进制数也不能有前导0的判断
            System.out.println(sbSum8.substring(1,sbSum8.length()));
        else
            System.out.println(sbSum8.toString());
    }

别人的思路

  1. 1位16进制可以代表4位2进制, 1位8进制可以代表3位二进制,得出3位16进制求和入栈输出表示4位8进制,然后出栈输出。

  2. 我的理解为:
    3位16进制,一位16进制可用4位2进制表示,即:34=12。
    4位8进制,一位8进制可用3位2进制表示,即:4
    3-12
    所以,他们俩之间进行等价

  3. 完整代码(可通过测试):

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        new Main().systemScanner();
    }
    public void systemScanner() {
        Scanner jin = new Scanner(System.in);
        while (jin.hasNext()) {
            int length = jin.nextInt();
            for (int i = 0; i < length; i++){
                String strTmp=jin.next();
                tranform(strTmp.toCharArray(), strTmp.length());
            }
        }
    }
    /*
     * 3位16进制等价于4位8进制
     */
    int[] stack=new int[40000];
    public void tranform(char[] str, int length) {
        char[] buff = new char[4];
        int top = -1;
        for (int i = length - 1; i >= 0; i -= 3) {
            int sum = 0;
            for (int j = 0; j < 3 && i - j >= 0; j++) {// i-j>=0防止不够三个的情况
                int tmp = str[i - j] >= '0' && str[i - j] <= '9' ? str[i - j] - '0'
                        : str[i - j] - 'A' + 10;//区分是数字,还是字符,进行对应转换
                sum+=(tmp<<(4*j));//这句很重要,通过这句就可以从16变成10进制了,不过,不知道为什么?是如何得出的呢?而且进行累加之后就能得到最终的结果很神奇
            }
            stack[++top]=sum;//sum的结果是16进制转化10进制的结果,每3个16进制变成10进制,再变8进制
        }
        while(stack[top]==0){//排除前导为0的判断
            top--;
        }
//      for(int i=top;i>=0;i--){//直接输出会丢失前导0,因为此转化成8进制并不是最左边的情况,应该保留0
//          System.out.print(Integer.toOctalString(stack[i]));//从10进制转化成8进制
//      }
        for(int i=top;i>=0;i--){
            String str1=Integer.toOctalString(stack[i]);//从10进制转化成8进制
            if(i!=top&&str1.length()<4){
                //不是最左边的一个,就不用去掉前导0,而默认是去掉0的,所以要进行补会
                for(int y=0;y<4-str1.length();y++)
                    System.out.print("0");
            }
            System.out.print(str1);
        }
        System.out.println();

    }
}

参考通过的例子

【蓝桥杯】16转换8进制

扩展知识

char buff[4];
sprintf(buff ,"%o", stack[i]);

相对应的java代码为

// Store the formatted string in 'result'
String result = String.format("%4d", i * j);
// Write the result to standard output
System.out.println( result );
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,743评论 0 33
  • 一、 1、请用Java写一个冒泡排序方法 【参考答案】 public static void Bubble(int...
    独云阅读 1,359评论 0 6
  • 计算机二级C语言上机题库(南开版) 1.m个人的成绩存放在score数组中,请编写函数fun,它的功能是:将低于平...
    MrSunbeam阅读 6,338评论 1 42
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,605评论 18 399
  • 我那无处安放的感情 我那未完成的青春 还爱吗? 嗯~ 嘿~朋友 不过不过,只有一点点了~ 请不要拿我的执念审判我~...
    洁珮阅读 286评论 0 0