我的任务是编写一个程序,找到给定的电话号码 可能的文字编码并打印出来。 这是我从字母到数字的映射:
E | J N Q | R W X | D S Y | F T | A M | C I V | B K U | L O P | G H Z
e | j n q | r w x | d s y | f t | a m | c i v | b k u | l o p | g h z
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
我还有包含所有可能单词的dictionary.txt文件。 因此,如果我的程序输入数字562482作为输入,那么输出将是:
562482: mir Tor
因为我在我的dictionary.txt字词' mir'和' Tor'。
首先,我决定创建一个特殊的结构来快速搜索字典中的单词并使用它:
Map<String, List<String>> bucketedWords = new HashMap<>()
其中key是字典中每个单词的编号,value是带有这样编号的字典中所有单词的列表。在启动程序后初始化此结构。 条目示例:
key: 562 values: [mir, mix]
所以我可以在字典中快速搜索并按数字接收所有可能的单词。
现在我对第二部分感到好奇。 每个输入数字具有2 ^(n-1)个连续子串的组合。 我将输入数字拆分为这样的组合列表,并检查我的bucketWord字典中的每个条目。 如果输入数字的长度变长,那么我花了很多时间寻找子串的所有组合。这是解决此类问题的正确方法,还是有更好的解决方案?
有关任务here
的更多信息修改
SpiderPig告诉我,我已经使用了递归但是变化很小,这有助于我找到后续数字的单词:
private List<List<String>> _findEncodings(String number, int startAt, boolean isNumber) {
LinkedList<List<String>> result = new LinkedList<>();
if (startAt == number.length()) {
result.add(new LinkedList<String>());
return result;
}
for (int endAt = startAt + 1; endAt <= number.length(); endAt++) {
List<String> words = bucketedWords.get(number.substring(startAt,
endAt));
if (words != null) {
List<List<String>> encodings = null;
if((endAt - startAt == 1) && (words.size() == 1) && (isNumeric(words.get(0)))){
if(isNumber){
continue;
}
encodings = _findEncodings(number, endAt, true);
}else{
encodings = _findEncodings(number, endAt, false);
}
for (String word : words) {
for (List<String> encoding : encodings) {
List<String> enc = new LinkedList<>(encoding);
enc.add(0, word);
result.add(enc);
}
}
}
}
return result;
}
public List<List<String>> findEncodings(String number) {
return _findEncodings(number, 0, false);
}
public boolean isNumeric(String str)
{
try
{
Double.parseDouble(str);
}
catch(NumberFormatException nfe)
{
return false;
}
return true;
}
此外,我还在我的水桶中添加了数字。那是我的工作。
答案 0 :(得分:2)
您应该使用trie而不是Map。 Trie一次一个地理解数字序列。 https://en.wikipedia.org/wiki/Trie
在这种情况下,它是O(max(len(word)))对于电话号码是O(7)~O(1)