本周的算法題難度級(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),做出來了也是有成就感的。。。