問題
給定一個包含[0,9]中數字的整數數組,任務是打印所有可能的字母
數字可以表示的組合,數字到字母的映射(就像在電話按鈕上)正在被跟蹤,注意0和1不映射到任何字母。所有映射如下圖所示:
寫一個程序把0到9的數字轉換成字母,且程序需要支持將0到99的數字轉換成字母。
例如:
Input:arr[] ={3,4}
Output: DG DH DI EG EH EI FG FH FI
Input: arr[] = {2}
Output: A B C
解題思路
初始化數據
使用HashMap來存儲數字和字母的映射關係,其中數字作爲key,字母作爲value,因爲一個數字對應了多個字母,且每個數字對應的字母個數又不盡相同,所以這裏的value使用List集合來進行存放。代碼如下:
public static void initDigitsMap(){
digitsMap=new HashMap<>();
digitsMap.put("0",Arrays.asList(""));
digitsMap.put("1",Arrays.asList(""));
digitsMap.put("2",Arrays.asList("A","B","C"));
digitsMap.put("3",Arrays.asList("D","E","F"));
digitsMap.put("4",Arrays.asList("G","H","I"));
digitsMap.put("5",Arrays.asList("J","K","L"));
digitsMap.put("6",Arrays.asList("M","N","O"));
digitsMap.put("7",Arrays.asList("P","Q","R","S"));
digitsMap.put("8",Arrays.asList("T","U","V"));
digitsMap.put("9",Arrays.asList("W","X","Y","Z"));
}
數字轉換爲字母
首先從用戶鍵盤中輸入一串數字,且這組數字必須在0-99的範圍內,這裏可以通過while循環和正則表達式判斷來保證用戶輸入內容的合法性,將用戶輸入的數字進行切割,得到一個只包含0-9的數組,在循環中將每個數組元素作爲key從HashMap數據中查詢出該數字映射的字母集合,之後再次將這些集合添加到一個嶄新的List集合中,且該集合元素類型爲String數組,這樣就能把每個數字對應的字母集合放入到String數組中,然後將其作爲數據源傳遞給遞歸方法中,進行多數組排列組合操作,返回一個最終排列結果的List集合,最後直接遍歷該集合打印數據即可。代碼如下:
public static void digitsToLetters(){
System.out.println("Please input digits from 0 to 9:");
//輸入按鍵數字1-9
String digits="";
while(true){
digits=input.next();
if(!digits.matches("[0-9]{1,2}")){
System.out.println("輸入不合法!只能輸入0-99的數字,請重新輸入:");
}else{
break;
}
}
StringBuilder arrInput=new StringBuilder("Input:arr[] ={");
String[] arrStr=digits.split("");
List<String[]> dataList=new ArrayList<String[]>();
for(int i=0;i<arrStr.length;i++){
arrInput.append(arrStr[i]);
if(i<arrStr.length-1){
arrInput.append(",");
}
//先將多個list中的數據都添加到同一個集合中作爲數據源
List<String> lettersList=digitsMap.get(arrStr[i]);
if(lettersList.size()>0){//沒有數據的集合不能強行轉換爲數組
String[] letterArr= (String[]) lettersList.toArray();
dataList.add(letterArr);
}
}
arrInput.append("}");
//遞歸實現多數組排列組合,並返回最終的排列集合
List<String[]> resultList= makeupLetters(dataList,0,null);
//打印輸入內容
System.out.println(arrInput.toString());
System.out.print("Output:");
//打印輸出排列組合結果
for(int i=0;i<resultList.size();i++){
String[] letterArr=resultList.get(i);
System.out.print(" ");
for(String s: letterArr){
System.out.print(s);
}
}
}
遞歸實現多數組排列組合
在遞歸方法中,我們需要傳入需要包含多數組的數據源集合,當前遞歸的數組在集合中的索引位置以及返回的排列結果集合,在方法中對數組進行遍歷,通過複製數組進入擴容和增加新元素,並添加到結果集合中,然後再次遞歸調用自身方法,每遞歸一次集合索引位置加1,直到遍歷完最後一個數組才返回最終的排列結果集合。代碼如下:
private static List<String[]> makeupLetters(List<String[]> dataList, int index, List<String[]> resultList){
if(index==dataList.size()){
return resultList;
}
List<String[]> resultList0=new ArrayList<String[]>();
if(index==0){//第一列數組默認有多少個字母就添加多少個排列數據
String[] dataArr=dataList.get(0);
for(String s : dataArr){
resultList0.add(new String[]{s});
}
}else{
String[] dataArr=dataList.get(index);
for(String[] dataArr0: resultList){
for(String s : dataArr){
//複製數組並擴充新元素
String[] dataArrCopy=new String[dataArr0.length+1];
System.arraycopy(dataArr0, 0, dataArrCopy, 0, dataArr0.length);
dataArrCopy[dataArrCopy.length-1]=s;
//追加到結果集
resultList0.add(dataArrCopy);
}
}
}
return makeupLetters(dataList,++index,resultList0);
}