如何从电话号码打印字符串关联作为文本?

时间:2009-12-07 06:34:40

标签: java algorithm recursion

我需要一些帮助,我正在为一个项目编写一个方法。该方法将电话号码更改为文本字符串列表。

你知道2-9在手机上有与他们相关的信件。我想制作一个将7位数字改为字符串列表的转换器。我希望看到所有可能性。我已经删除了所有的1和0,因为他们没有给他们任何信件。例如:如果我们的数字只有两位数,那么37就是:

DP DQ DR DS EP EQ ER ES FP FQ FR FS。

到目前为止,我一直在尝试使用嵌套for循环,但是没有得到正确的输出。任何帮助或想法都会很好。感谢

(我不是要求完整的代码,而是更像是如何做的建议)

8 个答案:

答案 0 :(得分:2)

解决方案的关键是使用下面代码中声明的pad数组。 例如,在部分电话号码763中,

pad [7]将产生数组{'p','q','r'},

pad [6]将产生数组{'m','n','o'},

pad [3]将产生数组{'a','b','c'},

然后,使用递归方法getAlpha(int [] num,int next,char [] alpha)迭代每个组合可能性,形成字母进度的算法树。在树的每个叶/末节点处,是要附加到列表的完整字母阵列。当递归到前一个数字位置时,只能使用一个字母数组来重复使用/覆盖,因为只有在到达叶子/结束节点时才会附加字符串化的字母数组。 stringify(char [])不包含在这里。

getAlpha(int [] num)是从递归的数字位置0开始的入口点方法。每个递归级别处理电话号码的下一个数字。

public class Z{
  // 2D array [i][j]
  // use phone digit as array index i
  final char[][] pad = {
    {'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'},
  };

  // This will be the horrendously long list of possible alphabetic codes
  List<String> combinations = new ArrayList<String>();

  void getAlpha(int[] num, int next, char[]alpha){
    // iterate over all possible alphabets of next digit
    for (int i=0; i<pad[next].length; i++){
      //set,overwrite next cell of array with iterated alphabet
      alpha[next] = pad[next][i];
      if (i<num.length-1)
        //process next next digit
        getAlpha(num, next++, alpha);
      else
        //if end of number
        //append array to horrendously long list
        combinations.add(stringify(alpha));
    }
  }

  public void getAlpha(int[] num){
    getAlpha(num, 0, new char[num.length]);
  }
}

答案 1 :(得分:0)

如果我没记错的话,任何数字都不超过4个字母。

粗略的生成方式是从基数4中的0到4 ^(位数)-1计数,这将给出02031之类的数字,让0表示相关数字的第一个字母,1表示第二个等等。所有包含3的位置都有一个只有3个字母的数字的数字将被丢弃。

一个10位数字将产生一个超过一百万个基数4的数字列表。你被警告了。

编辑: 更优雅的方法是查看有多少4个(我们称之为x)字符数字和3个(我们称之为y)字符数字,并从0到4 ^ x * 3 ^ y-1计数。通过使用/和%运算符,每个数字可以转换为如上所示的数字序列。

例如: 如果8和9是4个字符的数字,并且您想要一个数字258的字符串表示列表,则从0到3 ^ 2 * 4-1 = 35。 以21号为例,例如: 向后工作,最右边的角色(从8开始),你可以通过

获得角色

21%4 = 1,1表示't'

将你所做的信息与你所做的分开21/4 = 5.

下一个字符:

5%3 = 2,2表示'l'

5/3 = 1。

最终角色:

1%3 = 1代表'b'

这会让你得到字符串“blt”。

这个算法有一些书籍保留,但你不会从上面的例子中获得开销计数和丢弃,并且你没有得到递归算法所具有的内存开销。

答案 2 :(得分:0)

您可能想要使用递归。你说不给你代码,所以这里只是一个大纲:

// This is the function you're writing.  It prints every possible
// string you can make with the digits of that phone number by
// calling another function recursively.
void printAllPossibilities(String phoneNumber) {
  recursivePrintAllPossibilities("", phoneNumber);
}

void recursivePrintAllPossibilities(String prefix, String phoneNumber) {
  // 1. If the phone number is empty, just print the prefix and return.
  // 2. If the phone number is not empty, take the first digit and convert it
  //   into possible letters.  For each letter, add that letter to the prefix
  //   and then call recursivePrintAllPossibilities with the new prefix, and
  //   with the now-truncated phone number.
}

假设您的示例输入为“37”,主函数printAllPossibilities将调用recursivePrintAllPossibilities,其前缀为“”“,phoneNumber =”37“。该功能将自称三次:

  1. 一次使用prefix =“D”和phoneNumber =“7”
  2. 一次使用prefix =“E”和phoneNumber =“7”
  3. 使用前缀=“F”和phoneNumber =“7”
  4. 这些电话中的第一个将再次召唤自己四次:

    1. 一次使用prefix =“DP”和phoneNumber =“”
    2. 一次使用prefix =“DQ”和phoneNumber =“”
    3. 一次使用prefix =“DR”和phoneNumber =“”
    4. 一次使用prefix =“DS”和phoneNumber =“”
    5. 这些调用中的每一个都只会打印前缀。然后控制返回一个级别,并以“E”开头的所有输出,依此类推。当控制返回到原始功能时,它将打印出所有可能性。

      学会以递归方式“思考”需要练习,但这将成为第二天性。

答案 3 :(得分:0)

基于h2g2java,但修复了错误以使其正常工作。

public class Z{
  // 2D array [i][j]
  // use phone digit as array index i
  final char[][] pad = {
    {'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'},
  };

  // This will be the horrendously long list of possible alphabetic codes
  List<String> combinations = new ArrayList<String>();

  void getAlpha(int[] num, int next, char[]alpha){
    // iterate over all possible alphabets of next digit

    for (int i=0; i<pad[num[next]].length; i++){
      //set,overwrite next cell of array with iterated alphabet
      alpha[next] = pad[num[next]][i];
      if (next<num.length-1) {
        //process next next digit
        getAlpha(num, next + 1, alpha);
      } else {
        //if end of number
        //append array to horrendously long list
        combinations.add(String.valueOf(alpha));
      }
    }
  }

  public void getAlpha(int[] num){
    getAlpha(num, 0, new char[num.length]);
  }
}
  • 从递归next返回时,在进行上一次调用时已更新,因此在执行for循环的下一次迭代时,它会查找与pad中不同的数字。而不是在调用中递增它,我们只传递下一个值。
  • 使用数字中的位置而不是该位置的数字来查找填充数组中的字符。例如。如果这个数字只是233那就是01a,01b,01c而不是add,ade ......
  • if (i<num.length-1)错了。我们希望以递归方式为数字中的每个数字调用一次,以便:if (next < num.length-1)
  • stringify(alpha)更改为String.valueOf(alpha)

答案 4 :(得分:0)

我认为这样做的最终目的是确定哪些现有单词与给定的电话号码匹配(如phonespell.org)。如果是这样,你可以应用你将在过程中使用的字典,并避免必须首先生成大量无意义的单词。所以一般来说:

  • 将第一个数字的所有可能字母添加到解决方案列表
  • 表示其余数字:
      每个解决方案
    • 从解决方案列表中删除解决方案
    • 表示当前数字的每个可能字母:
      • candidate = solution + letter
      • 如果有以候选人开头的词典单词,则将候选人添加到解决方案列表

您可以通过将仍然与您的解决方案匹配的所有词典单词复制到每次迭代之间的新缩减词典中来优化此目的。

答案 5 :(得分:0)

这是一个古老的话题,但无论如何......

递归解决方案非常好!但是想提出一些替代方案,让我们称之为“OOP解决方案”.. :)也许有人觉得它很有用..

您只需要创建一个能够跟踪数字表示状态的类:

private class DigitInLetter {
    private int digit;
    private char[] letters;
    private int currentLetterIndex;

    private DigitInLetter(int digit) {
        this.digit = digit;
        this.letters = pad[digit];//the same pad from recursive solution..
        currentLetterIndex = 0;
    }

    /**
     * Changes selected letter to the next one. If there is no more items  
     * in the array, changes it to one with index 0.
     * 
     * @return true if index reset to 0, otherwise false.
     */
    public boolean changeToNextLetter() {
        if (currentLetterIndex < letters.length-1) {
            currentLetterIndex++;
            return false;
        } else {
            currentLetterIndex = 0;
            return true;
        }
    }

    public char getCurrentLetter() {
        return letters[currentLetterIndex];
    }
}

有了这个,你应该简单地写一个行循环来创建一个与给定数字相对应的数组DigitInLetter []。并且,使用以下简单代码迭代所有可能性:

    int digitIndex = 0;
    while (digitIndex < digitInLetterArray.length) {
        somewhere.add(digitInLetterArray.TO_STRING);//do here whatewer you want.. e.g. some simple toString can be written for DigitInLetter[]... just be careful to do not accumulate tons of references to the same objects being changed.. )) 

        for (digitIndex = 0; digitIndex < digitInLetterArray.length && 
            digitInLetterArray[digitIndex].changeToNextLetter(); digitIndex++);
    }

建模类中有更多代码行,但结果非常简单。

答案 6 :(得分:0)

我今天接受采访并问了这个问题。我在一次采访中挣扎但是在那之后我尝试了并且确实实施了它。这是Java中的解决方案。

public static List<String> deriveWordCombinations(String number){

    List<String> finalWord = new ArrayList<String>();
    List<String> iterative = new ArrayList<String>();
    finalWord.add("");
    for(int i=0;i<number.length();i++){
        char c = number.charAt(i);
        String stringForNumber = map.get(c);
        for(String s:finalWord){
            for(char cs: stringForNumber.toCharArray()){
                iterative.add(s+cs);
            }
        }
        finalWord = iterative;
        iterative = new ArrayList<String>();
    }

    return finalWord;
}

static final HashMap<Character,String> map = new HashMap<Character,String>(){
    {
    put('2',"abc");
    put('3',"def");
    put('4',"ghi");
    put('5',"jkl");
    put('6',"mno");
    put('7',"pqrs");
    put('8',"tuv");
    put('9',"wxyz");
    }
};

答案 7 :(得分:-1)

package LinkedList;

import java.util.ArrayList;
import java.util.LinkedHashMap;

public class letterDigits {

    private static LinkedHashMap<String, String> map;

    private static ArrayList<String> deriveWordCombinations(String number) {

        ArrayList<String> finalWord = new ArrayList<String>();
        ArrayList<String> iterative = new ArrayList<String>();
        finalWord.add("");

        for (int i = 0; i < number.length(); i++) {
            String c = number.substring(i, i + 1);

            String stringForNumber = map.get(c);
            for (String s : finalWord) {
                for (char cs : stringForNumber.toCharArray()) {
                    iterative.add(s + cs);
                }
            }
            finalWord = iterative;
            iterative = new ArrayList<String>();
            System.out.println("Final Word->" + finalWord);
        }

        return finalWord;
    }

    public void makeHashMap() {
        map.put("1", "");
        map.put("2", "ABC");
        map.put("3", "DEF");
        map.put("4", "GHI");
        map.put("5", "JKL");
        map.put("6", "MNO");
        map.put("7", "PQRS");
        map.put("8", "TUV");
        map.put("9", "WXYZ");
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        letterDigits obj = new letterDigits();
        map = new LinkedHashMap<String, String>();
        obj.makeHashMap();
        // System.out.println(map);
        String str = "345";
        ArrayList<String> word = letterDigits.deriveWordCombinations(str);
        System.out.println("Word->" + word);

    }
}

产生输出:

Final Word->[D, E, F]
Final Word->[DG, DH, DI, EG, EH, EI, FG, FH, FI]
Final Word->[DGJ, DGK, DGL, DHJ, DHK, DHL, DIJ, DIK, DIL, EGJ, EGK, EGL, EHJ, EHK, EHL, EIJ, EIK, EIL, FGJ, FGK, FGL, FHJ, FHK, FHL, FIJ, FIK, FIL]
Word->[DGJ, DGK, DGL, DHJ, DHK, DHL, DIJ, DIK, DIL, EGJ, EGK, EGL, EHJ, EHK, EHL, EIJ, EIK, EIL, FGJ, FGK, FGL, FHJ, FHK, FHL, FIJ, FIK, FIL]

输入&#34; 345&#34;