原题:https://leetcode.com/problems/letter-combinations-of-a-phone-number/
思路:
就是排列组合全部输出嘛!如果用递归做的话,函数进栈出栈估计会挺费事儿的,所以想个循环呗。假设我们要输出的是一个矩阵形式的东西,第i行j列是第i个答案的第j个字幕,那么主要问题是求出这个字母是啥。
拿原题中给的例子看,对应第一列的输出是a,a,a,b,b,b,c,c,c;第二列是d,e,f,d,e,f,d,e,f. 可以比较容易知道,第一列的字母是每3列变换一次,第二列则是每1列变换一次。即,假设最终由N个可能结果(N行),每一列代表按了一个数字键,其对应字母有m[j]个那么:
- 第1列(j=0)字母是每Y[0] = N/m[j]改变一次的;
- 第2列(j=1)字母是每Y[1]/m[j]改变一次的;
- 以此类推…
所以第i行第j列的字符应该是chr[ dight[i] ] [ (j/Y[j])%当前数字对应可能结果的个数 ]
其中j/Y[j]是当前跳到了哪一个“轮回”了,比如例子里面j=4,Y[0]=9/3=3,那么就应该跑到第二个字母”b”了。
代码:
struct ChrNode{
int size;
ChrNode() {}
};
const char chrs[][4] = { {' '}, {'X'}, {'a','b','c'}, {'d','e','f'},
{'g','h','i'}, {'j','k','l'}, {'m','n','o'},
{'p','q','r','s'}, {'t','u','v'}, {'w','x','y','z'}};
class Solution {
public:
int childSize(char c) {
switch (c) {
case '2': case '3': case '4': case '5': case '6': case '8': return 3;
case '7': case '9': return 4;
}
return 1;
}
void makeNode(ChrNode* node, char d) {
node->size = childSize(d);
}
vector<string> letterCombinations(string digits) {
vector<ChrNode> nodes;
//Build tree
int digiSize = digits.size();
int solutionSz = 1;
for(int i=0; i<digiSize; i++){
ChrNode node;
makeNode(&node, digits[i]);
nodes.push_back(node);
solutionSz *= childSize(digits[i]);
}
vector<string> solutions;
if(solutionSz <= 1)
return solutions;
for(int row=0; row<solutionSz; row++)
solutions.push_back("");
char c;
int jmp = solutionSz;
for(int i=0; i<digiSize; i++) {
jmp /= nodes[i].size;
int jmp_diff;
for(int j=0; j<solutionSz; j++) {
jmp_diff = j / jmp;
c = chrs[digits[i] - '0'][jmp_diff % nodes[i].size];
solutions[j] += c;
}
}
return solutions;
}
};