【问题标题】:Encoding phone number to word and searching dictionary将电话号码编码为单词并搜索字典
【发布时间】:2015-05-13 16:32:54
【问题描述】:

我有一个任务。我试过通过堆栈溢出搜索。

我需要阅读一个包含电话号码的文本文件。这部分我知道怎么做。

接下来我需要根据以下编码将电话号码转换为所有可能的单词排列:

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

并对照我要阅读的字典文件检查它们。 (阅读部分我已经知道怎么做了)

有人可以推荐一个好的算法来编码电话号码和检查字典吗?

到目前为止,我尝试的所有方法都引发了 OutOfMemory 异常,并且分配指定不能是这种情况。

【问题讨论】:

  • 请发布一些代码,以便我们调查异常并改进它。
  • 对于 10 位数字,您将获得大约 60M 组合,因此如果您尝试将所有组合存储在集合中,则默认 JVM 设置很可能会出现 OutOfMemory 错误。
  • 他们会给你一本字典来查词吗?这将极大地限制搜索空间,并大大加快您的代码速度。

标签: java encoding


【解决方案1】:

这里是:

static char[][] letters = {"Ee".toCharArray(),      // 0
                           "JNQjnq".toCharArray(),  // 1
                           "RWXrwx".toCharArray()   // 2
                           //.... add remaining
                          };

static Set<String> words = new HashSet<>(Arrays.asList(
                           "Stack", 
                           "Overflow", 
                           "foo", 
                           "bar" 
                           //... add other words
                           ));

// main method
public void generateAndCheckAll(String number) {
    int[] num = new int[number.length()];         // store number as digits
    int[] ind = new int[number.length()];         // store letter indices
    int i = 0;
    for (char c : number.toCharArray()) {         // convert String to int array
        num[i++] = c - '0';
    }
    do {
        String word = generateWord(num, ind);
        System.out.println(word + (words.contains(word) ? " is contained" : " is not contained"));
    } while (next(num, ind));
}


// generate word by number array and index array
public String generateWord(int[] num, int[] ind) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < ind.length; i++) 
        sb.append(letters[num[i]][ind[i]]);
    return sb.toString();
}


// switch index array to next
public boolean next(int[] num, int[] ind) {
    int i = ind.length - 1;
    while (i >= 0 && ind[i] == letters[num[i]].length - 1) // search for the index that can be incremented
        i--;
    if (i < 0)
        return false;
    ind[i]++;                                              // increment such index
    for (int j = i + 1; j < num.length; j++)               // change remaining indices to 0
        ind[j] = 0;
    return true;
}

这里的主要思想是在每次迭代时存储字母索引数组并基于它生成一个新单词。例如,对于数字 201 和索引数组 [0, 0, 5],将生成单词 REq:第 0 个字母代表数字 2,第 0 个字母代表数字 0,第 5 个字母代表数字 @ 987654327@。

然后在字典中查找该单词并将索引数组切换到下一个。从末尾扫描我们搜索可以递增的索引(这样就不会溢出给定位置的数字的字母数):我们不能递增“5”(因为数字1只有6个字母),但是我们可以增加“0”。所以索引数组被更改为[0, 1, 0],一切都一遍又一遍地重复,直到所有索引都达到最大值。

要查看它是如何工作的,请在逐步模式下调试此代码。很容易理解并将相同的想法应用于许多其他类似的任务。


顺便说一句,这不是最有效的方法,因为字典大小(我想是 10-100K)很可能小于组合计数(10 位数字约为 60M)。如果你真的不需要生成所有的组合,你可以进行字典的准备:

  1. 为字典中的每个单词生成一个数字,

  2. 将每个生成的数字映射到对应的单词(words),并将这些映射收集到哈希集合中。

然后,对于您收到的号码,您只需查看给定号码是否存在一个单词(单词)。这种方法需要较长的准备阶段和较大的空间,但查找速度显着提高。

【讨论】:

    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 2021-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 2017-03-04
    相关资源
    最近更新 更多