题目
LeetCode:Letter Combinations of a Phone Number
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入: "23"
输出: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
思路
写此题时,对c++并不了解,因此用的c写,花费了好些时间。
首先开辟足够的空间,这个不难计算,因此注释也就不多赘述,关键是下面的字符串操作。
核心是分部分处理,例如1对应abc,就将所有字符串分成三个部分,比如一共27个字符串排列的话,前9个则全部a开头,中间9个全b开头,后面9个全部c开头。
紧接着比如第二个数字是3,对应ghi,则将第一次分的三部分取出一部分也就是9个字符串,分成三部分,前3个字符串全部加g,中间三个全部加h,后面三个全部加i,其他18个字符串也如此处理。
……
代码
/**
* Return an array of size *returnSize.
* Note: The returned array must be malloced, assume caller calls free().
*/
char** letterCombinations(char* digits, int* returnSize) {
//正常求法是递归求解,但是c写起来真的是太不方便了,不能像c++那样string + string
//而且一般递归问题改成非递归都很麻烦,不过经历了一下午还是解决了
char* cur = digits;
int cur_divide = 0;//当前划分区间
int prev_divide = 0;//前一次划分区间
char** ret = NULL;
const char ch[10][5] = { "","","abc","def","ghi","jkl","mno","pqrs","tuv", "wxyz" };
int str_legth = strlen(digits) + 1;//包含'\0',所以+1
int i = 0;
*returnSize = 1;
while (*cur != '\0')
{
if (*cur != '7' && *cur != '9')
{
(*returnSize) *= 3;
}
else
{
(*returnSize) *= 4;
}
cur++;
}
cur = digits;
cur_divide = (*returnSize);
ret = (char**)malloc(sizeof(char*) * (*returnSize));
for (int i = 0; i < (*returnSize); i++)
{
*(ret + i) = (char*)malloc(sizeof(char) * str_legth);
}
if (str_legth == 1)
{
*returnSize = 0;
return ret;
}
while (*cur != '\0')
{
int start = 0;
int ret_start = 0;
int ch_index = 0;//字符的位置下标
//这里的str_legth和前面的意义不同,前面表示给的digits的长度,这里当做数字对应的字符串长度
//比如2对应就是3——"abc",7对应4——"pqrs"
str_legth = strlen(ch[*cur - '0']);
prev_divide = cur_divide;
cur_divide /= str_legth;
//区间划分很重要,当数字对应的字符是3个,就在前一个基础上分为3个区,4个即在前一个基础上划分四个区间
while (start < prev_divide)
{
ret_start = start;//这里比较难懂,之后会写博客来配图解释
while (ret_start < (*returnSize))
{
//由于区间是分散的,所以每次开始的位置都不一样
for (i = ret_start; i < ret_start + cur_divide; i++)
{
*(*(ret + i) + (cur - digits)) = ch[*cur - '0'][ch_index];//在对应位置放入字符
}
ret_start += prev_divide;
}
ch_index++;
start += cur_divide;
}
cur++;
}
//最后在字符串尾部加'\0'
for (i = 0; i < (*returnSize); i++)
{
*(*(ret + i) + (cur - digits)) = '\0';
}
return ret;
}