• 大数据十六进制转八进制


     今天在做蓝桥杯题目的时候看到一题十六进制转八进制的题目,题目如下:

    问题描述

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

    输入格式

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

    输出格式

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

    注意

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

    样例输入

    2
    39
    123ABC

    样例输出

    71
    4435274

    提示

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


    十六进制转化为八进制最直接想到的有两种方法:

      1.将十六进制转换为十进制再转换为八进制

      2.将十六进制转换为二进制再转换为八进制

         分析:在第一种方法中用int类型来储存十进制数的话那么最大能处理80 000 000(H)也就是 2147483648 (D),本题要求处理大数据,那么必须用数组储存。用第一种方法就涉及到了大整数的加法,模,除法。

                    第二种方法相对于第一种方法而言比较容易,只用定义一个字符数组就可以储存二进制数,每一个十六进制可以转换为4位2进制数,然后每3位二进制数可以转换为一个八进制数,在本题中输入的十六进制没有前导零,所以在十六进制最高的四位最小出现“0001”若最后三位相加为0那么就不输出即可。

      以下是实现代码

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #define N 100001
    char str[N];
    void prin(char *a,int n)
    {
    	int i;
    	for(i=n-1;i>=0;i--){
    		printf("%d",a[i]);
    	}
    	putchar('
    ');
    }
    void change(int use)
    {
    	int num=0;
    	char two[N*4];
    	int  w[4]={1,2,4,8};
    	int i=0,j=0,cnt2=0,cnt8=0;
    	//totwo 
    	while(use>=0){
    		num=isdigit(str[use])?str[use]-'0':str[use]-'A'+10;
    		use--;
    		 for(i=0;i<4;i++){
    		 	two[cnt2++]=num&w[i];
    		 }
    	}
    	//twoto
    	for(i=0;i<cnt2;){	
    	  for(num=0,j=0; i<cnt2&&j<3 ;j++){
    	  	if(two[i++]) num+=w[j];
    	  }
    	  two[cnt8++]=num;
    	}
    	if(!two[cnt8-1]) cnt8--;
    	//printf
    	for(i=cnt8-1;i>=0;i--)
    	{
    		printf("%d",two[i]);
    	}
    	putchar('
    ');
    }
    int main(void)
    {
    	int n;
    	scanf("%d",&n);
    	if(n>=1&&n<=10){
    		while(n--){
    			scanf("%s",str);
    			change(strlen(str)-1);
    		}
    	}
    	return 0; 
    }
    


    对于上述方法浪费的空间太大!我利用C语言对于底层的操作,位运算可以大大减少空间复杂度以及时间复杂度

    实现如下

    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #define N 100001
    char str[N];
    int save=0;
    void change(int use,int state)
    {
    	int num;
    	if(use>=0){
    		if(state!=3){
    			num=isdigit(str[use])?str[use]-'0':str[use]-'A'+10;
    			num<<=state;
    			num|=save;
    			save=num>>3;
    			change(use-1,state+1);
    			printf("%d",num%8);
    		}else{
    			num=save;
    			save>>=3;
    			change(use,0);
    			printf("%d",num%8);
    		}
    	}else{
    	  if(save){
    	  	printf("%d",save);
    	  	save=0;
    	  }	
    	}
    }
    int main(void)
    {
    	int num;
    	scanf("%d",&num);
    	if(num>=1&&num<=10){
    	while(num--){
    		scanf("%s",str);
    	   change(strlen(str)-1,0);	
    		printf("
    ");
    	}
    	}
    	return 0;
    }


    内存使用之所以不降反升的原因是因为使用了递归

    (作者水平有限,欢迎大家讨论批评)


  • 相关阅读:
    数据挖掘实践(45):实战--啤酒产量时序分析(三)
    数据挖掘实践(44):实战--啤酒产量时序分析(二)
    数据挖掘实践(43):实战--啤酒产量时序分析(一)
    数据挖掘实践(42):算法基础(十四)时间序列分析(五)
    Java 之 数组 案例(不重复的数组&回形数)
    Java 之 数组中常见的异常
    Java 之 数组 Arrays 工具类
    Java 之 数组常用算法
    Java 之 多维数组(二维数组)
    Java 之 一维数组
  • 原文地址:https://www.cnblogs.com/pzqu/p/9457658.html
Copyright © 2020-2023  润新知