本周的算法題難度級別“Medium”,用了我三天工作之余的時間,總算過了,效率較低
題目:給你一串?dāng)?shù)字,在9宮格鍵盤上輸入這串?dāng)?shù),需要求所有可能得到的字符串
分析:題目其實就是手機(jī)的九宮格輸入法,把按鍵的字母進(jìn)行排列組合即可。明確了題目,下面就來實現(xiàn)本道題
- 確定行數(shù)和列數(shù)
我們可以發(fā)現(xiàn),列數(shù)其實就是你輸入數(shù)字的個數(shù),行數(shù)就是數(shù)字代表字母個數(shù)的乘積
- 確字每行每列顯示的字母
我發(fā)現(xiàn)的規(guī)律是:第一列的字母是你輸入的第一個數(shù)字所代表的字母的循環(huán),第二列是第二個數(shù)字對應(yīng)字母的循環(huán)。。。最后一列循環(huán)的次數(shù)是最后一列字母的個數(shù)/最后一列字母的個數(shù)
,倒數(shù)第二列的循環(huán)次數(shù)是(倒數(shù)第二列字母的個數(shù) * 倒數(shù)第一列字母的個數(shù))/倒數(shù)第二列字母的個數(shù)
,倒數(shù)第三列的循環(huán)次數(shù)是(倒數(shù)第三列字母的個數(shù) * 倒數(shù)第二列字母的個數(shù) * 倒數(shù)第一列字母的個數(shù))/倒數(shù)第三列字母的個數(shù)
。。。
通過以上的兩個規(guī)則我們就能把這道題搞定了,由于這兩個規(guī)則不好理解,我們先舉個例子來理解下這兩條規(guī)則,假設(shè)我們輸入了2?3?4三個數(shù)字,則排列組合如下圖:
通過第一條規(guī)則來確字行數(shù)和列數(shù):2代表a/b/c三個字母,3代表d/e/f三個字母,4代表g/h/i三個字母,則行數(shù)為3*3*3=27行,輸入了三個數(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個a,9個b,9個c的循環(huán)填序即可。思路上實現(xiàn)以后,我們就用代碼來實現(xiàn):
char** letterCombinations(char* digits, int* returnSize) {
//列數(shù)就是輸入數(shù)字的個數(shù)
int column = (int)strlen(digits);
//str用于存儲輸入數(shù)字所對應(yīng)的字母
char **str = malloc(column * sizeof(char *));
//如果輸入的個數(shù)為0
if (column == 0) {
*returnSize = 0;
return str;
}
//通過計算每個數(shù)字所對應(yīng)字母的個數(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;
}
這道題用了一天多的空閑時間就總結(jié)出了規(guī)律,思路一直沒錯(應(yīng)該不是最優(yōu)思路),但代碼實現(xiàn)卻花了我近兩天的時間,不得不嘆息想法和做法之間還是有一些距離,代碼實現(xiàn)中主要的問題是內(nèi)存問題,著實的被strlen這個函數(shù)坑了好久,又被'\0'這個坑坑了半天,也使得我對指針、c語言內(nèi)存機(jī)制等方面又有了新的認(rèn)識,看來光有想法還不夠,程序猿就要多敲代碼,將想法落地才能更好的成長,做出來了也是有成就感的。。。