3.2电话号码对应英语单词

方法一、 
神奇的双重while循环。 
注:显然可以利用这种方法,打印出任意一个N维数组的任意组合。

 
个人理解:此双重循环的关键在于 answer[ ] 数组以及索引 k 。answer[ ] 数组中存放了number[ ]对应的所有可能的单词组合,而索引 k 则负责把所有可能的组合给找出来。

初始状态下,answer[ ] 中全为0 ,k 从  n -1 开始,不断向0推进,列举所有可能。 

例如,设现在推进到了i,( i >= 0  && i <= n - 1)。那么此刻, 0~ i之前的组合都还未列举出来,都还为0。而 i ~ n -1 之后的组合都已穷举出来了, 

第i位已经列举了0 ~  answer[i] 的情况。即已经打印出来的英语单词组合有 {0 , 0 , 0, ...., 0 ~ answer[i] , 0 ~ total[i + 1] , 0 ~ total[i + 2], ...,0 ~ total[n - 1] }. 
第answer[ i ] 每变化一次,都要把 answer(i +1 ~ n - 1)的情况穷举一次,而answer(0~ i )之间的值不变,直至i小于0。(就像递归 或者 n重for循环,i 即第 i 重循环!)

方法二、递归(实质就是DFS) 
实例代码: 



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


//键盘数字上的字符
char c[10][10] = {
    "", "", "ABC", "DEF",
    "GHI", "JKL", "MNO",
    "PQRS", "TUV", "WXYZ"};
//0到9每个数组键上字符的个数
int total[] = {0, 0, 3, 3, 3, 3, 3, 4, 3, 4};
const int TelLength = 3; //电话号码的位数
int number[TelLength];//每位电话号码的数字
int answer[TelLength]; //每位数字上字符的下标


//方法一
void OutputTelephone(int number[])
{
    while (true)
    {

            for (int i = 0; i < TelLength; i++)
                cout << c[number[i]][answer[i]] << " ";
            cout << endl;


        int k = TelLength - 1;
        //一次循环一次从第k个键向前移动一位
        while (k >= 0)
        {

            if (answer[k] < total[number[k]] - 1)
            {
                //第k个键移动
                answer[k]++;
                break; //这里只要有一个键的一个位置发生一次变化,就退出,打印一次。
            }
            else
            {
                //第k个键移动完毕,回到0,开始遍历上一个键。
                //此时,继续内部循环。下次循环,处理上一个键。
                answer[k] = 0;
                k--;
            }


        }
        if (k < 0)
            break;


    }
}


//方法2
void RecursiveOutput(int number[], int answer[], int index)
{
    if (index == TelLength)
    {
        for (int i = 0; i < TelLength; i++)
            cout << c[number[i]][answer[i]] << " ";
        cout << endl;
        return;
    }
    //上下来回反弹的都以递归啊,类似于dfs
    for (answer[index] = 0; answer[index] < total[number[index]]; answer[index]++)
    {
        RecursiveOutput(number, answer, index + 1);
    }


}


int main()
{
    int number[] = {3, 4, 5};
    OutputTelephone(number);
    RecursiveOutput(number, answer, 0);
    return 0;
}




FROM: http://kmplayer.iteye.com/blog/769293

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值