蓝桥杯-十六进制转八进制

蓝桥杯原题

这个题还是有点含金量,第一遍做出来,很可能会超时,比如以下代码:

import java.util.ArrayList;
import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int times = sc.nextInt();
        for (int i=0;i<times;i++){
            long Ten = 0;
            String str = sc.next();
            Ten = SixToTen(str);
            TenToEight(Ten);
        }
    }

    public static long SixToTen(String str){
        long  result = 0;
        char[] ch = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        for (int i=0;i<str.length();i++){
            long t=1;
            for (int j=0;j<ch.length;j++){
                if (str.charAt(i) == ch[j]){
                    for (int m=0;m<str.length()-i-1;m++){
                        t = 16*t;
                    }
                    t = j*t;
                }   
            }
            result = result+t;
        }
        return result;
    }

    public static void TenToEight(long i){
        boolean t = true;
        ArrayList<Long> result = new ArrayList<Long>();
        if (i == 0){
            result.add((long)0);
        }else{
            while(t){
                if (i==0){
                    break;
                }else{
                    result.add(i%8);
                    i = i/8;
                }
            }
        }
        for (int n=result.size()-1;n>=0;n--){
            System.out.print(result.get(n));
        }
        System.out.println();
    }
}

在这我用的是十六进制转十进制再转八进制,在十六转十的过程中,用到了三层循环,复杂度比较高,所以非常非常非常容易超时,再加上用的是long类型,还会涉及到位数不够的情况。
这段代码测试了两次,均提示我说运行超时,当我把蓝桥的测试数据打开的时候,被吓到了……如下:
input:

10
76
931FA
C9DAB2B36C
248B87D6AE33F9A
62D7183A5D5789E4B2D6
B441E2411DC709E111C7E1E7ACB6F8CAC0BB2FC4C8BC2AE3BAAAB9165CC458E199CB89F51B135F7091A5ABB0874DF3E8CB45
43A5EB93B0441E9CA4C2B0FB3D30875CBF29ABD5B1ACF38984B35AE882809DD4CFE7ABC5C61BAA52E053B4C3643F204EF259D2E98042A948AAC5E884CB3EC7DB925643FD34FDD467E2CCA406035CB2744CB90A63E51C9737903343947E02086541E4C48A99630AA9AECE153843A4B190274EBC955F8592E30A2205A485846248987550AAF2094EC59E7931DC650C7451CC61C0CB2C46A1B3F2C349FAFF763C7F8D14DDFF946351744378D62C59285A8D7915614F5A2AC9E0D68ACA6248A9227AB8F1930EE38AC7A9D239C9B026A481E49D53161F9A9513FE5271C32E9C21D156EB9F1BEA57F6AE4F1B1DE3B7FD9CEE2D9CCA7B4C242D26C31D000B7F90B7FE48A131C7DEBFBE58165266DE56E1EDF26939AF07EC69AB1B17D8DB62143F2228B51551C3D2C7DE3F5072BD4D18C3AEB64CB9E8CBA838667B6ED2B2FCAB04ABAE8676E318B402A7D15B30D2D7DDB78650CC6AF82BC3D7AA805B02DD9AA523B7374A1323EE6B516D1B81E5F709C2C790EDAF1C3FA9B0A1DBC6DABC2B5ED267244C458752002B106D6381FAD58A7E193657BDE0FE029120F8379316891F828B8D24A049E5B86D855BCFED56765F9DA1AC54CAEAF9257ABC67B451BC70B0E52817DD1B704A6B418A83FD4A9CA4C89E1A6E779F8D9E9DF18747591E5B314C05763EDCD59632423CA83F14D6F073D784DB2B7001643A6760
F9F0DD6DDD0A59E241DC1ED720287896286F5CC3ADDF6C1ADF6ED35F477B0022981E5E1FBFE1BFB8E26B5BA93253275BF6A44B3FA1051CDFE3B3F5D2725A9A580FD5B04525B3182FCD2B3FDA124ACA3C901406A2B55CD8B95D48D13E379F1CCBCDFC39FEE4ACC5523AA0BDEF57E63A1F81CBABA9F45CAAED48D06BFB3D16836042BED57CAC84761BFEB59A0C81304908BB781E4BBDF230D2E977374B97BD0B6B7D38B736428826A0F2729BE2290256DC304E875C9D4B3FB2125AE3D0CD3130D6114989517ACA97DAA2485181EB31C07D2C6A5BCC587E048A6D2BEACD6FE206F225C708461B41FDB5AD087C5DC4FCAEEC3A3437A42E51B065D6E4332F71B109D3317681AB0FCBF31C9F1C23BA46B4F983AF9214D13AC3DDF6C03F3E9854C4D47741A5576812BE0B5CB8BF647B930687EC881DF76191F9C468C1736EEF1E59635EB6CBD2C73B00068C8FFEDEDEC2826D114DC1F8824924FA079056E25A5DDBAECEB90A18C51F919A83AE980E25BF06DD486427DFDEE6F708AA642625CE4C4298AFDD7AC48AA81B0C5608C2D801543EDEEAB5479C1342E4E4AEC719F1A46E33C1D761EFDF22116051E18FA714C72FAE0756835527748E4DF2E728E3DAAF94E9B3F37489C0D4E12D40469296D35673027F5E4D70D54B668A7C00F96CCB23F2562A468B650A1719186285BE1893B861E8B2E3E49EEA5F37799FE4DFC738F99E140F8E31D1B21E9882867563C9BC24A39A2195266D87B203
………

数据量非常大,也就说明不用传统的方式去解决以上问题,需要用一个新的方式去降低算法复杂度
在这里百度了一会,发现十六进制转二进制再转八进制,可以明显减少算法复杂度
思路是:十六进制数的每一位相当于一个四位二进制,同时八进制数每一位相当于三位二进制数,于是,只要把二进制数的每一位存到char型数组中,然后三位三位一取,并把确实的0补上去,就可以完成。

//代码已经通过测试,以下代码为借鉴的代码
//http://www.jianshu.com/p/e06bac9c9231
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();

 }
}

另一种用java的做法:
http://blog.csdn.net/yl_freedom/article/details/41650523

或者是像下面这样做:(C/C++)

#include <iostream>  
#include <string>  
using namespace std;  

int main()  
{  
    int n = 0, i = 0, j = 0, temp = 0, nNum = 0;  
    char ch;  
    string strHex[10];  
    string strBin[10];  
    string strOct[10];  

    cin>>n;  
    for (i = 0; i < n; ++i)  
    {  
        cin>>strHex[i];  
    }  

    //十六进制转二进制  
    for (i = 0; i < n; ++i)  
    {  
        j = 0;  
        while (strHex[i][j])  
        {  
            switch(strHex[i][j])  
            {  
            case '0': strBin[i] += "0000"; break;  
            case '1': strBin[i] += "0001"; break;  
            case '2': strBin[i] += "0010"; break;  
            case '3': strBin[i] += "0011"; break;  
            case '4': strBin[i] += "0100"; break;  
            case '5': strBin[i] += "0101"; break;  
            case '6': strBin[i] += "0110"; break;  
            case '7': strBin[i] += "0111"; break;  
            case '8': strBin[i] += "1000"; break;  
            case '9': strBin[i] += "1001"; break;  
            case 'A': strBin[i] += "1010"; break;  
            case 'B': strBin[i] += "1011"; break;  
            case 'C': strBin[i] += "1100"; break;  
            case 'D': strBin[i] += "1101"; break;  
            case 'E': strBin[i] += "1110"; break;  
            case 'F': strBin[i] += "1111"; break;  
            default:break;  
            }  
            ++j;  
        }  
    }  

    //二进制转化为八进制  
    for (i = 0; i < n; ++i)  
    {  
        j = strBin[i].size()-1;//获得长度  
        while (strBin[i][j] && j>=0)  
        {  
            temp = 3;  
            nNum = 0;  
            while (temp-- && j>=0)  
            {  
                if ('1' == strBin[i][j])  
                {  
                    switch(temp)  
                    {  
                    case 0: nNum += 4; break;  
                    case 1: nNum += 2; break;  
                    case 2: nNum += 1; break;  
                    default:break;  
                    }  
                }  
                --j;  
            }  
            strOct[i] += (nNum+'0');  
        }  
    }  

    //字符串逆序  
    for (i = 0; i < n; ++i)  
    {  
        temp = strOct[i].size()-1;  
        for (j = 0; j <= temp/2; ++j)  
        {  
            ch = strOct[i][j];  
            strOct[i][j] = strOct[i][temp-j];  
            strOct[i][temp-j] = ch;  
        }  
    }  
    //打印  
    for (i = 0; i < n; ++i)  
    {  
        j = 0;  
        while (strOct[i][j++] == '0');//跳过前面的0  

        for(--j; j < strOct[i].size(); ++j)  
        {  
            cout<<strOct[i][j]-'0';  
        }  
        /*if (i != n-1)*/  
            cout<<endl;  
    }  

    return 0;  
}  
//http://blog.csdn.net/jiluoxingren/article/details/50478759
#include <iostream>  
#include <string>  
#include <math.h>  
using namespace std;  
/* run this program using the console pauser or add your own getch, system("pause") or input loop */  

int main(int argc, char *argv[]) {  
    int n=0;  
    cin>> n;  

    string* Hex = new string[n];  
    string tmpOct;  
    string* Oct = new string[n];  

    for(int i=0;i<n;i++)  
    {  
        int CurBit = 0;  
        cin>>Hex[i];  

        tmpOct = "";  
        Oct[i] = "";  

        for(int j=Hex[i].size()-3;j>=0;j-=3)  
        {  
            int d = 0;  
            for(int k=0;k<3;k++)  
            {  
                int t = j+k;  
                // 16 To 10  
                if(Hex[i][t]>='0' && Hex[i][t]<='9')  
                {  
                    CurBit = Hex[i][t]-'0';  
                }  
                if(Hex[i][t]>='A' && Hex[i][t]<='F')  
                {  
                    CurBit = Hex[i][t]-'A'+10;    
                }  

                d = d * 16 + CurBit;  
            }  

            // 3bit hex to 4bit oct  
            int base = 7; // 111B  
            for(int k=0;k<4;k++)  
            {  
                tmpOct += (char)('0' + (d & base));  
                d = d >> 3;  
            }  
            d = 0;  
        }   

        // last less three  
        int rest = Hex[i].size() % 3;  
        if(rest != 0)  
        {  
            int d = 0;  
            for(int k=0;k<rest;k++)  
            {  
                // 16 To 10  
                if(Hex[i][k]>='0' && Hex[i][k]<='9')  
                {  
                    CurBit = Hex[i][k]-'0';  
                }  
                if(Hex[i][k]>='A' && Hex[i][k]<='F')  
                {  
                    CurBit = Hex[i][k]-'A'+10;    
                }  

                d = d * 16 + CurBit;  
            }  

            int base = 7; // 111B  
            int max = ceil(4.0 / 3.0 * rest);  
            // 1bit hex = 4/3 bit oct  
            for(int k=0;k<max;k++)  
            {  
                if(((k==max-1) && (d & base)!=0) || k<max-1)  
                    tmpOct += char('0' + (d & base));  
                d = d >> 3;  
            }  
        }  

        int j=tmpOct.size()-1;  
        // turn order  
        for(;j>=0;j--)  
        {  
            Oct[i] += tmpOct[j];  
        }  
    }  

    for(int i=0;i<n;i++)  
    {  
        cout<<Oct[i]<<endl;  
    }  

    cin>>n;  
    return 0;  
}  
//代码逻辑略复杂
//http://blog.csdn.net/sr_19930829/article/details/18677037
#include <iostream>  
#include <string.h>  
#include <stack>  
using namespace std;  

int fib(int n)//计算2的多少次方  
{  
    int sum=1;  
    if(n==0)  
        return 1;  
    else  
    {  
        for(int i=1;i<=n;i++)  
            sum*=2;  
        return sum;  
    }  
}  

string str[11];  

int two[400008];//因为16进制的位数不超过100000,所以换成二进制数位数不超过400000  

int main()  
{  
    int n,i,j,k;  
    cin>>n;  
    for(int k=1;k<=n;++k)  
    {  
        cin>>str[k];  
        memset(two,0,sizeof(two));  
        for( i=0;i<str[k].length();++i)//把十六进制的每一位变成4个二进制数,注意存放的顺序  
        {  
            if(str[k][i]>='0'&&str[k][i]<='9')  
            {  
                int temp=str[k][i]-'0';  
                int tap=4*(i+1);//把two数组每4个元素为一组,连续,当前的十六进制位为two数组的最大下标+1  
                while(temp)  
                {  
                    two[--tap]=temp%2;//首先要tap-1,因为two数组是从0开始的,这也解释了为什么上面说是最大下标+1  
                    temp/=2;  
                }  
            }  
            else  
            {  
                int temp=str[k][i]-55;//A-55得10  
                int tap=4*(i+1);  
                while(temp)  
                {  
                    two[--tap]=temp%2;  
                    temp/=2;  
                }  
            }  
        }//到目前为止把16进制转成了二进制  
        int count=0;//二进制数三位一组来转化为8进制  
        int sum=0;//连续三位二进制数的值  
        stack<int>q;  
        for(j=4*str[k].length()-1;j>=0;--j)//从two数组的存数的最大下标开始处理,每三个为一组,转化为8进制,保存在栈中  
        {  
            sum+=(two[j]*fib(count++));  
            if(count==3)  
            {  
                q.push(sum);  
                sum=0;  
                count=0;  
            }  

        }  
        int sum1=0;//考虑处理的末尾,可能最后一组少于3个,有可能是一个,也可能是两个,单独处理,单独输出  
        int c=0;  
        for(int m=4*str[k].length()%3-1;m>=0;--m)//4*str[k].length()%3判断还剩下几个  
        {  
            sum1+=two[c++]*fib(m);  
        }  
        if(sum1!=0)  
            cout<<sum1;//单独输出  
        if(q.top()==0)  
            q.pop();//去除前导0,如果有的话  
        while(!q.empty())  
        {  
           cout<<q.top();//从栈中输出  
            q.pop();  
        }  
        cout<<endl;  
    }  
    return 0;  
}  
#include <iostream>  
#include <string>  
using namespace std;  

int main()  
{  
    int n;  
    cin>>n;  
    for(int k=1;k<=n;k++)  
    {  
        string s1,s2;//s1为输入的原始的十六进制串,s2为转化成的二进制串  
        cin>>s1;  
        s2="";//初始化  
        for(int i=0;i<s1.length();i++)//遍历,字符串上加上每一位  
        {  
            switch(s1[i])  
            {  
                case '0':s2+="0000";break;  
                case '1':s2+="0001";break;  
                case '2':s2+="0010";break;  
                case '3':s2+="0011";break;  
                case '4':s2+="0100";break;  
                case '5':s2+="0101";break;  
                case '6':s2+="0110";break;  
                case '7':s2+="0111";break;  
                case '8':s2+="1000";break;  
                case '9':s2+="1001";break;  
                case 'A':s2+="1010";break;  
                case 'B':s2+="1011";break;  
                case 'C':s2+="1100";break;  
                case 'D':s2+="1101";break;  
                case 'E':s2+="1110";break;  
                case 'F':s2+="1111";break;  
                default:break;  
            }  
        }  
        int len=s2.length();  

        if(len%3==1)//三个二进制为一位八进制,二进制串前面补0,确保二进制串的长度为3的倍数  
            s2="00"+s2;  
        else if(len%3==2)  
            s2="0"+s2;  
        int flag=0;  
        for(int i=0;i<=s2.length()-3;i+=3)  
        {  
            int num=4*(s2[i]-'0')+2*(s2[i+1]-'0')+(s2[i+2]-'0');  
            if(num)  
                flag=1;//忽略前导0  
            if(flag)  
                cout<<num;  
        }  
        cout<<endl;  
    }  
    return 0;  
} 
//http://blog.csdn.net/u011669700/article/details/18563955
#include<iostream>  
#include<cstring>  
#include<cstdio>  
using namespace std;  
int stack[40000];  
void transform(string str, int length)  
{  
    char buff[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++)  
        {  
            int temp = str[i - j] >= '0' && str[i - j] <= '9' ? str[i - j] - '0' : str[i - j] - 'A' + 10;  
            sum += (temp << (4 * j));  
        }  
        stack[++top] = sum;  
    }  
    while( stack[top] == 0)  
    {  
        top--;  
    }  
    for(int i = top; i >= 0; i--)  
    {  
        printf("%04o", stack[i]);  
    }  
    cout<<endl;  
}  

int main()  
{  
    string *str;  
    int n;  
    cin>>n;  
    str = new string[n];  
    for(int i = 0; i < n; i++)  
    {  
        cin>>str[i];  
    }  
    for(int i = 0; i < n; i++)  
    {  
        transform(str[i], str[i].size());  
    }  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值