把0到9的數字轉換成電話按鈕上的字母

問題

給定一個包含[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);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章