电话号码代表的数字排列

时间:2009-12-05 05:39:01

标签: permutation phone-number

我在2天内接受采访,我很难找到这个问题的解决方案: 我想要做的是..对于任何电话号码..程序应该打印出它代表的所有可能的字符串。例如。)数字中的2可以用'a'或'b'或'c'代替,3代表'd''e''f'等。这样可以形成多少可能的排列给出了电话号码。 我不希望任何人为它编写代码...一个好的算法或伪代码会很棒。

谢谢

10 个答案:

答案 0 :(得分:8)

这是受欢迎的对应表:

d = { '2': "ABC",
'3': "DEF",
'4': "GHI",
'5': "JKL",
'6': "MNO",
'7': "PQRS",
'8': "TUV",
'9': "WXYZ",
}

鉴于此,或任何其他d,(可执行)伪代码将一串数字转换为所有可能的字母串:

def digstolets(digs):
  if len(digs) == 0:
    yield ''
    return
  first, rest = digs[0], digs[1:]
  if first not in d:
    for x in digstolets(rest): yield first + x
    return
  else:
    for x in d[first]:
      for y in digstolets(rest): yield x + y

可调整取决于你想要对输入字符串中不包含在29之间的字符做什么(这个版本只是回应它们! - )。

例如,

print list(digstolets('1234'))

在此版本中发出

['1ADG', '1ADH', '1ADI', '1AEG', '1AEH', '1AEI', '1AFG', '1AFH', '1AFI', 
 '1BDG', '1BDH', '1BDI', '1BEG', '1BEH', '1BEI', '1BFG', '1BFH', '1BFI',
 '1CDG', '1CDH', '1CDI', '1CEG', '1CEH', '1CEI', '1CFG', '1CFH', '1CFI']

编辑:OP要求更多解释,这是尝试。函数digstolets(数字到字母)采用一串数字digs,并产生一系列字符串,可以是字母或“非数字”。 01在此处计为非数字,因为它们不会扩展为字母,就像空格和标点符号一样 - 仅包括数字29扩展为字母(大多数情况下各有三种可能性,两种情况中有四种,因为7可以扩展到PQRS中的任何一种,9可以扩展为WXYZ中的任何一种。

首先,基本情况:如果没有剩下(字符串digs为空),唯一可能的结果是空字符串,就是这样,这个递归调用完成,完成,kaput。

如果digs非空,则可以将其分为“head”,第一个字符和“tail”,所有其余字符(第一个字符后面的0个或多个字符)。

如果是非数字,“head”要么保持原样在输出中;如果是数字,则扩展为三种或四种可能性中的任何一种。在任何一种情况下,头部的一个,三个或四个可能的扩展必须与尾部的每个可能的扩展连接,即递归调用,以获得尾部的所有可能的扩展(因此我们遍历所有可能的扩展)尾部的扩展,并且产生头部的一个,三个或四个可能的扩展中的每一个与每个可能的尾部扩展连接在一起。然后,再一次,这就是全部,伙计们。

我不知道如何用更基本的术语来表达这一点 - 如果在此之后OP仍然丢失,我只能建议对递归的所有内容进行认真的全面审查。删除递归以支持显式维护的堆栈不能简化这个概念性的展示 - 取决于所涉及的语言(听听OP完全适合的语言会很好!),递归消除可以是一个重要的优化,但它绝不是概念简化 ......! - )

答案 1 :(得分:2)

如果在接受采访时问我,我首先要解决这个问题。你必须解决哪些问题?

首先,您需要将数字映射到一组字母。有些数字会映射到不同数量的字母。首先要弄清楚如何存储这些数据。基本上你想要一个数字的地图到一组字母。

一旦你在那里,让它变得更容易,你将如何生成1位数字的所有“单词”?基本上如何遍历映射到给定数字的集合。有多少种可能性?

好的,现在下一步是,你有两个数字,想要生成所有单词。如果你只是手动做,你会怎么做?您将从第一个数字的第一个字母和第二个数字的第一个字母开始。然后转到第二个数字的下一个字母,保留第一个字母的第一个字母,等等。把它想象成数字(基本上是两个数字的集合中的索引,每个数字映射到3个字母):

00,01,02,10,11,12,20,21,22

那你如何在代码中生成那个数字序列呢?

一旦你能做到这一点,将它翻译成代码应该是微不足道的。

祝你好运!

答案 2 :(得分:2)

Java中的另一个版本。

首先,它根据电话号码的每个数字选择字符数组。然后使用递归生成所有可能的排列。

public class PhonePermutations {
    public static void main(String[] args) {
        char[][] letters = 
            {{'0'},{'1'},{'A','B','C'},{'D','E','F'},{'G','H','I'},{'J','K','L'}, 
            {'M','N','O'},{'P','Q','R','S'},{'T','U','V'},{'W','X','Y','Z'}};
        String n = "1234";
        char[][] sel = new char[n.length()][];
        for (int i = 0; i < n.length(); i++) {
            int digit = Integer.parseInt("" +n.charAt(i));
            sel[i] = letters[digit];
        }
        permutations(sel, 0, "");
    }

    public static void permutations(char[][] symbols, int n,  String s) {
        if (n == symbols.length) {
            System.out.println(s);
            return;
        }
        for (int i = 0; i < symbols[n].length; i ++) {
            permutations(symbols, n+1, s + symbols[n][i]);
        }
    }
}

答案 3 :(得分:1)

这是一个计数问题,因此通常有助于找到解决较小问题的解决方案,然后考虑它如何扩展到您的一般情况。

如果您有一个 1 数字电话号码,会有多少种可能性?如果您有 2 位数怎么办?你是如何从一个移动到另一个的,你能想出一种解决 n 数字的方法吗?

答案 4 :(得分:1)

以下是我提出的建议:

import java.util.*;

public class PhoneMmemonics {

    /**
     * Mapping between a digit and the characters it represents
     */
    private static Map<Character,List<Character>> numberToCharacters = new HashMap<Character,List<Character>>();

    static {
        numberToCharacters.put('0',new ArrayList<Character>(Arrays.asList('0')));
        numberToCharacters.put('1',new ArrayList<Character>(Arrays.asList('1')));
        numberToCharacters.put('2',new ArrayList<Character>(Arrays.asList('A','B','C')));
        numberToCharacters.put('3',new ArrayList<Character>(Arrays.asList('D','E','F')));
        numberToCharacters.put('4',new ArrayList<Character>(Arrays.asList('G','H','I')));
        numberToCharacters.put('5',new ArrayList<Character>(Arrays.asList('J','K','L')));
        numberToCharacters.put('6',new ArrayList<Character>(Arrays.asList('M','N','O')));
        numberToCharacters.put('7',new ArrayList<Character>(Arrays.asList('P','Q','R')));
        numberToCharacters.put('8',new ArrayList<Character>(Arrays.asList('T','U','V')));
        numberToCharacters.put('9',new ArrayList<Character>(Arrays.asList('W','X','Y','Z')));
    }

    /**
     * Generates a list of all the mmemonics that can exists for the number
     * @param phoneNumber
     * @return
     */
    public static List<String> getMmemonics(int phoneNumber) {

        // prepare results
        StringBuilder stringBuffer = new StringBuilder();
        List<String> results = new ArrayList<String>();

        // generate all the mmenonics
        generateMmemonics(Integer.toString(phoneNumber), stringBuffer, results);

        // return results
        return results;
    }

    /**
     * Recursive helper method to generate all mmemonics
     * 
     * @param partialPhoneNumber Numbers in the phone number that haven't converted to characters yet
     * @param partialMmemonic The partial word that we have come up with so far
     * @param results total list of all results of complete mmemonics
     */
    private static void generateMmemonics(String partialPhoneNumber, StringBuilder partialMmemonic, List<String> results) {

        // are we there yet?
        if (partialPhoneNumber.length() == 0) {

                   //Printing the pnemmonics
                   //System.out.println(partialMmemonic.toString());

            // base case: so add the mmemonic is complete
            results.add(partialMmemonic.toString());
            return;
        }

        // prepare variables for recursion
        int currentPartialLength = partialMmemonic.length();
        char firstNumber = partialPhoneNumber.charAt(0);
        String remainingNumbers = partialPhoneNumber.substring(1);

        // for each character that the single number represents
        for(Character singleCharacter : numberToCharacters.get(firstNumber)) {

            // append single character to our partial mmemonic so far
            // and recurse down with the remaining characters
            partialMmemonic.setLength(currentPartialLength);
            generateMmemonics(remainingNumbers, partialMmemonic.append(singleCharacter), results);
        }
    }
}

答案 5 :(得分:0)

使用递归和良好的数据结构来保存可能的字符。由于我们正在讨论数字,因此数组数组可以正常工作。

char [] [] toChar = {{'0'},{'1'},{'2','A','B','C'},...,{'9', 'W','X'。 'Y'}};

请注意,此数组数组中的第i个数组包含与电话上第i个按钮对应的字符。即,tochar [2] [0]为'2',tochar [2] [1]为'A'等。

递归函数将索引作为参数。它将有一个for循环,遍历替换字符,用该数组中的一个替换该索引处的char。如果长度等于输入字符串的长度,则输出字符串。

在Java或C#中,您可能希望使用字符串缓冲区来保存更改的字符串。

function recur(index)
    if (index == input.length) output stringbuffer
    else
        for (i = 0; i < tochar[input[index]].length; i++)
             stringbuffer[index] = tochar[input[index]][i]
             recur(index + 1)

答案 6 :(得分:0)

我想到的一个问题是0和1应该在这样一个系统中变成什么样的问题?否则,你所拥有的东西基本上可以递归地通过2-9范围内每个值的字母,以简单的蛮力方式来生成所有值。

假设北美地区的电话号码长度正常并且最初忽略特殊区域代码,那么还有一个问题是,有多少位数代表4个值而不是3个,而7和9往往会得到那些经常未使用的字母Q和Z,因为计数范围从3 ^ 10 = 59,049到4 ^ 10 = 1,048,576。后者是1024平方,我刚才注意到了。

答案 7 :(得分:0)

OP似乎要求实施,因为他正在努力理解上面的伪代码。也许这Tcl script会有所帮助:

array set d {
    2 {a b c}
    3 {d e f} 
    4 {g h i}
    5 {j k l}
    6 {m n o}
    7 {p q r s}
    8 {t u v}
    9 {w x y z}
}

proc digstolets {digits} {
    global d

    set l [list]
    if {[string length $digits] == 0} {
        return $l
    }

    set first [string index $digits 0]
    catch {set first $d($first)}

    if {[string length $digits] == 1} {
        return $first
    }

    set res [digstolets [string range $digits 1 end]]
    foreach x $first {
        foreach y $res {
            lappend l $x$y
        }
    }

    return $l
}

puts [digstolets "1234"]

答案 8 :(得分:0)

#include <sstream>
#include <map>
#include <vector>

map< int, string> keyMap;

void MakeCombinations( string first, string joinThis , vector<string>& eachResult )
{
    if( !first.size() )
        return;

    int length = joinThis.length();
    vector<string> result;

    while( length )
    {
        string each;
        char firstCharacter = first.at(0);
        each =  firstCharacter;
        each += joinThis[length -1];
        length--;

        result.push_back(each);     
    }

    first = first.substr(1);

    vector<string>::iterator begin = result.begin();    
    vector<string>::iterator end = result.end();
    while( begin != end)
    {
        eachResult.push_back( *begin);
        begin++;
    }

    return MakeCombinations( first, joinThis, eachResult);
}


void ProduceCombinations( int inNumber, vector<string>& result)
{
    vector<string> inputUnits;

    vector<string> finalres;

    int number = inNumber;
    while( number )
    {
        int lastdigit ;

        lastdigit = number % 10;
        number = number/10;
        inputUnits.push_back( keyMap[lastdigit]);
    }

    if( inputUnits.size() == 2)
    {
        MakeCombinations(inputUnits[0], inputUnits[1], result);
    }
    else if ( inputUnits.size() > 2 )
    {
        MakeCombinations( inputUnits[0] , inputUnits[1], result);

        vector<string>::iterator begin = inputUnits.begin();    
        vector<string>::iterator end = inputUnits.end();


        begin += 2;
        while(  begin != end )
        {
            vector<string> intermediate = result;
            vector<string>::iterator ibegin = intermediate.begin(); 
            vector<string>::iterator iend = intermediate.end(); 

            while( ibegin != iend)
            {
                MakeCombinations( *ibegin , *begin, result);
                //resultbegin =  
                ibegin++; 
            }
            begin++;            
        }
    }
    else
    {

    }

    return;
}

int _tmain(int argc, _TCHAR* argv[])
{
    keyMap[1] = "";
    keyMap[2] = "abc";
    keyMap[3] = "def";
    keyMap[4] = "ghi";
    keyMap[5] = "jkl";
    keyMap[6] = "mno";
    keyMap[7] = "pqrs";
    keyMap[8] = "tuv";
    keyMap[9] = "wxyz";
    keyMap[0] = "";

    string  inputStr;
    getline(cin, inputStr);

    int number = 0;

    int length = inputStr.length();

    int tens = 1;
    while( length )
    {
        number += tens*(inputStr[length -1] - '0');
        length--;
        tens *= 10;
    }

    vector<string> r;
    ProduceCombinations(number, r);

    cout << "[" ;

    vector<string>::iterator begin = r.begin(); 
    vector<string>::iterator end = r.end();

    while ( begin != end)
    {
        cout << *begin << "," ;
        begin++;
    }

    cout << "]" ;

    return 0;
}

答案 9 :(得分:0)

C程序:

char *str[] = {"0", "1", "2abc", "3def", "4ghi", "5jkl", "6mno", "7pqrs", "8tuv", "9wxyz"};

const char number[]="2061234569";

char printstr[15];

int len;

printph(int index)
{

     int i;
     int n;
     if (index == len)
     {
        printf("\n");
        printstr[len] = '\0';
        printf("%s\n", printstr);
        return;
     }

     n =number[index] - '0';
     for(i = 0; i < strlen(str[n]); i++)
     {
        printstr[index] = str[n][i];
        printph(index +1);
     }
}

致电

  printph(0);