原题: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; } };