部分文章内容为公开资料查询整理,原文出处可能未标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

编程之美--3.2电话号码对应英语单词(含多重循环变单重循环的思路)

注意:这题提供了多重循环变单重循环的思路

问题:

电话的号码案件一般可以用于输入字母。如用2可以输入A、B、C,用3可以输入D、E、F等。
对于号码5869872,可以依次输出其代表的所有字母组合。如:JTMWTPA、JTMWTB······
问题1: 设计程序,尽可能从这些字母组合中,找到一个有意义的单词来表述一个电话号码。如单词"computer"来描述号码26678837。
问题2: 对于一个号码,是否可以用一个单词代表?怎样才是最快的方法?

 

解答:

问题1

解法1:直接循环输出。
例如对于3位电话号码“287”,我们需要输出3位数字代表的每一种情况。因此我们采用三重循环,每次变化其中一位数字代表的字母。
char[][] c 代表每一位数字所能表示的字母。total[] 代表每一个数字对应的字母个数。如total[8]=3指数字8能代表3个字母。
Number[] = {2,8,7},数组存放了这3位电话号码
answer[i]代表从0开始第i位数字当前指向第几个字母。如answer[1]=2代表第1个数字指向的第2个字母。在“287”中,第1位为8,指向的第2个字母为v(从0开始)

public static void printWords(){
    char[][] c = {
            {}, //0
            {},    //1
            {'a','b','c'}, //2
            {'d','e','f'}, //3
            {'g','h','i'}, //4
            {'j','k','l'}, //5
            {'m','n','o'}, //6
            {'p','q','r','s'},    //7
            {'t','u','v'},    //8
            {'w','x','y','z'}    //9
    };
    int[] total = {0,0,3,3,3,3,3,4,3,4};//表示每个数字能代表几个字母
    int n = 3; //表示有3位数的号码,即3重循环
    int[] Number = {2,8,7};    //三位电话号码
    int[] answer = new int[n]; //代表每一位电话号码的代表的数字对应字母是哪一个

    for(answer[0] = 0 ; answer[0]<total[Number[0]]; answer[0]++){
        for(answer[1] = 0 ; answer[1]<total[Number[1]]; answer[1]++){
            for(answer[2] = 0 ; answer[2]<total[Number[2]]; answer[2]++){
                for(int i = 0 ; i < n ; i++){
                    System.out.print(c[Number[i]][answer[i]]);
                }
                System.out.print(" ");
            }
            System.out.println();
        }
    }        
}

运行结果:

atp atq atr ats 
aup auq aur aus 
avp avq avr avs 
btp btq btr bts 
bup buq bur bus 
bvp bvq bvr bvs 
ctp ctq ctr cts 
cup cuq cur cus 
cvp cvq cvr cvs 

 

解法2:

针对3位数的电话号码,3个循环可以处理。当电话号码位数变化时,就需要变换for循环的个数。下面的方法解决了这个问题。

public static void printWords2(){
    char[][] c = {
            {}, //0
            {},    //1
            {'a','b','c'}, //2
            {'d','e','f'}, //3
            {'g','h','i'}, //4
            {'j','k','l'}, //5
            {'m','n','o'}, //6
            {'p','q','r','s'},    //7
            {'t','u','v'},    //8
            {'w','x','y','z'}    //9
    };
    int[] total = {0,0,3,3,3,3,3,4,3,4};//表示每个数字能代表几个字母
    int n = 3; //表示有3位数的号码,即3重循环
    int[] Number = {2,8,7};    //三位电话号码
    int[] answer = new int[n]; //代表每一位电话号码的代表的数字对应字母是哪一个
    
    while(true){ //电话号码数量变化的时候,不需要变换循环的数量。原来的方法必须改变for循环的数量
        for(int i = 0 ; i < n ; i++){
            System.out.print(c[Number[i]][answer[i]]);
        }
        System.out.print(" ");
        int k = n-1;
        while(k>=0){
            if(answer[k]<total[Number[k]]-1){
                answer[k]++;
                break;
            }
            else{ //本层的字母遍历完了,需要改变上一层的一个字母,然后再遍历一次
                answer[k]=0;  
                k--;
                System.out.println();
            }
        }
        if(k<0)
            break;
    }
}

运行结果:

atp atq atr ats 
aup auq aur aus 
avp avq avr avs 

btp btq btr bts 
bup buq bur bus 
bvp bvq bvr bvs 

ctp ctq ctr cts 
cup cuq cur cus 
cvp cvq cvr cvs 

 

解法3:递归的方法

 

public static void RecursiveSearch(int[] Number, int[] answer, int index ,int n){
        if(index == n){
            for(int i = 0 ; i <n ; i++){
                System.out.print(c[Number[i]][answer[i]]);
            }
            System.out.print(" ");
            return ;
        }
        
        for(answer[index]=0 ; answer[index]<total[Number[index]]; answer[index]++){
            RecursiveSearch(Number,answer,index+1,n);
        }
        System.out.println();

    }

 

代码中Number、answer的含义同前,index代表对电话的第几位数字进行循环,n为电话号码的位数。

初始调用为RecursiveSearch(number,answer,0,n)

首先对第0位数字的total[Number[0]]种情况进行递归调用,层层向下进行。

 

问题2:

解法1:利用问题1,将数字能代表的所有字符全输出,然后匹配字符是否在字典中。

解法2:如果查询的次数较多,可以直接把字典内所有的单词先转换成数字,存到文件中,形成一本数字字典,然后在数字字典中查询电话号码。

 

posted @ 2015-06-26 22:15  流了个火  阅读(287)  评论(0)    收藏  举报
►►►需要气球么?请点击我吧!►►►
View My Stats