1. 简述
电话的号码盘一般可以用于输入字母。如用2可以输入A、B、C,用3可以输入D、E、F等。
对于号码5869872,可以依次输出其代表的所有字母组合。如:JTMWTPA、JTMWTB······
1) 设计程序,尽可能从这些字母组合中,找到一个有意义的单词来表述一个电话号码。如单词"computer"来描述号码26678837。
2) 对于一个号码,是否可以用一个单词代表?怎样才是最快的方法?
2. 思路
由于两个任务都需要判断一个字母组合是否是一个单词,所以必须预先存一份单词列表。
方法一:直接对号码进行深度优先搜索,空间基本上没怎么用,就是时间太大了。假设,单词列表长度为N,号码K位,一个按键3个字符(实际上,不是每个数字对应的字符个数都一样),这就是3^k种字符序列。每找到一个序列,还要去单词列表里面查找,O(N),这还没算每次字符序列和单词匹配的具体时间,总之时间复杂度很高。
方法二:空间换时间,这就有两个具体思路。
一个是从号码这边走,把每个号码映射为一个数字,然后把每个数字对应的字符串找到,再根据单词列表,找到单词,实际上是把方法1中的任务离线做好了。这样有一个问题一般手机都有11位(每位假设都可以是0-9),这就是10^11种,100G个数字,每种数字再用方法一的方法进行操作,复杂度可想而知。
另一个方法是从单词这边走,实际上,英语单词个数是有限的,常用单词也就几千,考GRE也就几万吧,假设10万个单词,我们找到每个单词对应的号码,也是10万。对这10万个单词可以用Lucene建个索引,或者搞个字典树,对于索引,每个号码挂上对应单词在单词列表中的下标,对于字典树,每个号码节点挂上对应单词在单词列表中的下标。
这样来个一个号码,找到这个号码是否存在于索引和字典树的复杂度基本上就是常数级别,如果找到了,就能找到对应单词在单词列表中下标,进一步找到单词,如果找不到号码,就说明没有对应单词。
3. 参考
编程之美,3.2节,电话号码对应英语单词