如何打印出给定电话号码可能代表的所有可能的字母组合?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何打印出给定电话号码可能代表的所有可能的字母组合?相关的知识,希望对你有一定的参考价值。
我刚试过第一次编程访谈,其中一个问题是编写了一个给出7位数电话号码的程序,可以打印每个号码可能代表的所有可能的字母组合。
问题的第二部分就是如果这是一个12位数的国际号码呢?这会对你的设计产生什么影响。
我没有在采访中写的代码,但我得到的印象是他对此不满意。 做这个的最好方式是什么?
在Python中,迭代:
digit_map = {
'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz',
}
def word_numbers(input):
input = str(input)
ret = ['']
for char in input:
letters = digit_map.get(char, '')
ret = [prefix+letter for prefix in ret for letter in letters]
return ret
ret
是迄今为止的结果清单;最初它填充了一个项目,空字符串。然后,对于输入字符串中的每个字符,它会从顶部定义的字典中查找与其匹配的字母列表。然后它将列表ret
替换为现有前缀和可能字母的每个组合。
使用列表L,其中L [i] =数字i可以表示的符号。
L [1] = @,。,! (例如)L [2] = a,b,c
等等。
然后你可以做这样的事情(伪C):
void f(int k, int st[])
{
if ( k > numberOfDigits )
{
print contents of st[];
return;
}
for each character c in L[Digit At Position k]
{
st[k] = c;
f(k + 1, st);
}
}
假设每个列表包含3个字符,我们对7个数字有3 ^ 7个可能性,12个有3 ^ 12个,这不是很多。如果你需要所有组合,我看不到更好的方法。你可以避免递归和诸如此类的东西,但无论如何你都不会比这更快。
public class Permutation {
//display all combination attached to a 3 digit number
public static void main(String ar[]){
char data[][]= new char[][]{{'a','k','u'},
{'b','l','v'},
{'c','m','w'},
{'d','n','x'},
{'e','o','y'},
{'f','p','z'},
{'g','q','0'},
{'h','r','0'},
{'i','s','0'},
{'j','t','0'}};
int num1, num2, num3=0;
char tempdata[][]= new char[3][3];
StringBuilder number = new StringBuilder("324"); // a 3 digit number
//copy data to a tempdata array-------------------
num1= Integer.parseInt(number.substring(0,1));
tempdata[0] = data[num1];
num2= Integer.parseInt(number.substring(1,2));
tempdata[1] = data[num2];
num3= Integer.parseInt(number.substring(2,3));
tempdata[2] = data[num3];
//display all combinations--------------------
char temp2[][]=tempdata;
char tempd, tempd2;
int i,i2, i3=0;
for(i=0;i<3;i++){
tempd = temp2[0][i];
for (i2=0;i2<3;i2++){
tempd2 = temp2[1][i2];
for(i3=0;i3<3;i3++){
System.out.print(tempd);
System.out.print(tempd2);
System.out.print(temp2[2][i3]);
System.out.println();
}//for i3
}//for i2
}
}
}//end of class
You find source (Scala) here和an working applet here.
由于0和1与字符不匹配,因此它们在数字中构建自然断点。但它们不会出现在每个数字中(开头的0除外)。从9位数字开始,更长的数字如+49567892345,可能会导致OutOfMemoryErrors。所以最好将一个数字分成像这样的组
- 01723 5864
- 0172 35864
如果从较短的部分可以理解的话,看看。我写了这样一个程序,并测试了我的朋友的一些数字,但很少发现较短的单词组合,可以在字典中检查匹配,更不用说单个,长单词。
所以我的决定是只支持搜索,没有完全自动化,通过显示可能的组合,鼓励手动分割数量,也许多次。
所以我找到了+ -RAD JUNG(+ -bycicle boy)。
如果你接受拼写错误,缩写,外来词,数字作为单词,单词中的数字和名称,你找到解决方案的机会要好得多,而不是摆弄。
246848 => 2hot4u (too hot for you)
466368 => goodn8 (good night)
1325 => 1FCK (Football club)
53517 => JDK17 (Java Developer Kit)
是人类可能观察到的事情 - 让算法发现这样的事情是相当困难的。
#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;
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;
}
Python解决方案非常经济,因为它使用生成器在内存使用方面是高效的。
import itertools
keys = dict(enumerate('::ABC:DEF:GHI:JKL:MNO:PQRS:TUV:WXYZ'.split(':')))
def words(number):
digits = map(int, str(number))
for ls in itertools.product(*map(keys.get, digits)):
yield ''.join(ls)
for w in words(258):
print w
显然itertools.product
正在为您解决大部分问题。但是写自己并不困难。这是一个go中的解决方案,小心重复使用数组result
生成所有解决方案,并使用闭包f
来捕获生成的单词。结合起来,这些可以在product
中使用O(log n)内存。
package main
import (
"bytes"
"fmt"
"strconv"
)
func product(choices [][]byte, result []byte, i int, f func([]byte)) {
if i == len(result) {
f(result)
return
}
for _, c := range choices[i] {
result[i] = c
product(choices, result, i+1, f)
}
}
var keys = bytes.Split([]byte("::ABC:DEF:GHI:JKL:MNO:PQRS:TUV:WXYZ"), []byte(":"))
func words(num int, f func([]byte)) {
ch := [][]byte{}
for _, b := range strconv.Itoa(num) {
ch = append(ch, keys[b-'0'])
}
product(ch, make([]byte, len(ch)), 0, f)
}
func main() {
words(256, func(b []byte) { fmt.Println(string(b)) })
}