每周一道算法題(十三)

本周的算法題難度級(jí)別“Medium”,用了我三天工作之余的時(shí)間,總算過了,效率較低

題目:給你一串?dāng)?shù)字,在9宮格鍵盤上輸入這串?dāng)?shù),需要求所有可能得到的字符串

分析:題目其實(shí)就是手機(jī)的九宮格輸入法,把按鍵的字母進(jìn)行排列組合即可。明確了題目,下面就來實(shí)現(xiàn)本道題

  • 確定行數(shù)和列數(shù)

我們可以發(fā)現(xiàn),列數(shù)其實(shí)就是你輸入數(shù)字的個(gè)數(shù),行數(shù)就是數(shù)字代表字母?jìng)€(gè)數(shù)的乘積

  • 確字每行每列顯示的字母

我發(fā)現(xiàn)的規(guī)律是:第一列的字母是你輸入的第一個(gè)數(shù)字所代表的字母的循環(huán),第二列是第二個(gè)數(shù)字對(duì)應(yīng)字母的循環(huán)。。。最后一列循環(huán)的次數(shù)是最后一列字母的個(gè)數(shù)/最后一列字母的個(gè)數(shù),倒數(shù)第二列的循環(huán)次數(shù)是(倒數(shù)第二列字母的個(gè)數(shù) * 倒數(shù)第一列字母的個(gè)數(shù))/倒數(shù)第二列字母的個(gè)數(shù),倒數(shù)第三列的循環(huán)次數(shù)是(倒數(shù)第三列字母的個(gè)數(shù) * 倒數(shù)第二列字母的個(gè)數(shù) * 倒數(shù)第一列字母的個(gè)數(shù))/倒數(shù)第三列字母的個(gè)數(shù)。。。

通過以上的兩個(gè)規(guī)則我們就能把這道題搞定了,由于這兩個(gè)規(guī)則不好理解,我們先舉個(gè)例子來理解下這兩條規(guī)則,假設(shè)我們輸入了2?3?4三個(gè)數(shù)字,則排列組合如下圖:

通過第一條規(guī)則來確字行數(shù)和列數(shù):2代表a/b/c三個(gè)字母,3代表d/e/f三個(gè)字母,4代表g/h/i三個(gè)字母,則行數(shù)為3*3*3=27行,輸入了三個(gè)數(shù)字,所以列數(shù)為3
通過第二條規(guī)則來確定字母:我們先看最后一列,循環(huán)次數(shù)是3/3=1,即只循環(huán)一次,則直接g-h-i的循環(huán)填序即可,看倒數(shù)第二列,循環(huán)次數(shù)是(3*3)/3=3,循環(huán)3次,則按照d-d-d,e-e-e,f-f-f循環(huán)填序即可,倒數(shù)第三列的循環(huán)次數(shù)是(3*3*3)/3=9,循環(huán)9次,即9個(gè)a,9個(gè)b,9個(gè)c的循環(huán)填序即可。思路上實(shí)現(xiàn)以后,我們就用代碼來實(shí)現(xiàn):
char** letterCombinations(char* digits, int* returnSize) {
    //列數(shù)就是輸入數(shù)字的個(gè)數(shù)
    int column = (int)strlen(digits);
    //str用于存儲(chǔ)輸入數(shù)字所對(duì)應(yīng)的字母
    char **str = malloc(column * sizeof(char *));
    //如果輸入的個(gè)數(shù)為0
    if (column == 0) {
        *returnSize = 0;
        return str;
    }
    //通過計(jì)算每個(gè)數(shù)字所對(duì)應(yīng)字母的個(gè)數(shù)的乘積來求出行數(shù)
    int row = 1;
    for (int i = 0;i < column; i++) {
        int num =  (int)(digits[i] - '0');
        if (num == 0) str[i] = " ";
        else if (num == 1) str[i] = "*";
        else if (num == 2) str[i] = "abc";
        else if (num == 3) str[i] = "def";
        else if (num == 4) str[i] = "ghi";
        else if (num == 5) str[i] = "jkl";
        else if (num == 6) str[i] = "mno";
        else if (num == 7) str[i] = "pqrs";
        else if (num == 8) str[i] = "tuv";
        else if (num == 9) str[i] = "wxyz";
        row *= (int)strlen(str[i]);
    }
    //result為結(jié)果
    char **result = malloc(row * sizeof(char *));
    for (int i = 0; i < row; i++) 
        result[i] = malloc(column+1);
    //為result填充字母
    for (int c = column - 1; c >= 0; c--) {
        //確定循環(huán)次數(shù)temp
        int temp = c,sum = 1;
        while (temp <= column - 1) {
            sum *= strlen(str[temp]);
            temp++;
        }
        temp = sum / strlen(str[c]);
        //按列填充字母
        int r = 0;
        while (r < row) {
            result[r][c] = str[c][r/temp%strlen(str[c])];
            r++;
        }
        //填充結(jié)束符'\0'
        if (c == 0) {
            int r = 0;
            while (r < row) {
                result[r][column] = '\0';
                r++;
            }
        }
    }
    //返回結(jié)果
    *returnSize = row;
    return result;
}

這道題用了一天多的空閑時(shí)間就總結(jié)出了規(guī)律,思路一直沒錯(cuò)(應(yīng)該不是最優(yōu)思路),但代碼實(shí)現(xiàn)卻花了我近兩天的時(shí)間,不得不嘆息想法和做法之間還是有一些距離,代碼實(shí)現(xiàn)中主要的問題是內(nèi)存問題,著實(shí)的被strlen這個(gè)函數(shù)坑了好久,又被'\0'這個(gè)坑坑了半天,也使得我對(duì)指針、c語(yǔ)言內(nèi)存機(jī)制等方面又有了新的認(rèn)識(shí),看來光有想法還不夠,程序猿就要多敲代碼,將想法落地才能更好的成長(zhǎng),做出來了也是有成就感的。。。

版權(quán)聲明:本文為 Crazy Steven 原創(chuàng)出品,歡迎轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)注明出處!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容