力扣17题——电话号码的字母组合
一道经典的用回溯法解决的问题
题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = “23”
输出:[“ad”,“ae”,“af”,“bd”,“be”,“bf”,“cd”,“ce”,“cf”]
示例 2:
输入:digits = “”
输出:[]
示例 3:
输入:digits = “2”
输出:[“a”,“b”,“c”]
代码
char phoneMap[11][5] = {"\0","\0","abc\0","def\0", "ghi\0", "jkl\0", "mno\0", "pqrs\0", "tuv\0", "wxyz\0"};
char* digits_tmp;
int digits_size;
char** combinations;
int combinations_size;
char* combination;
int combination_size;
void backtrack(int index){
if(index == digits_size){
char* tmp = malloc(sizeof(char) * (combination_size+1));
memcpy(tmp,combination,sizeof(char) * (combination_size + 1));
combinations[combinations_size++] = tmp;
}else{
char digit = digits_tmp[index];
char* letters = phoneMap[digit - '0'];
int len = strlen(letters);
for(int i = 0; i < len; i++){
combination[combination_size++] = letters[i];
combination[combination_size] = 0;
backtrack(index + 1);
combination[--combination_size]=0;
}
}
}
char ** letterCombinations(char * digits, int* returnSize){
combination_size = combinations_size=0;
digits_tmp = digits;
digits_size = strlen(digits);
if(digits_size == 0){
*returnSize = 0;
return combination;
}
int num = 1;
for(int i = 0; i <digits_size; i++) num*=4;
combinations = malloc(sizeof(char*)*num);
combination = malloc(sizeof(char) * (digits_size+1));
backtrack(0);
*returnSize = combinations_size;
return combinations;
}
可以看到回溯法对于这种带分支的枚举问题很有效,一般回溯问题还有限制条件,用于剪掉不满足条件的。这个题所有的都是可行解。
回溯法经典框架:
void backtracking(int depth){
if(size == depth){
具体的操作,如保存可行解
}else{
初始化一些变量
for(int i = 0; i < numsSize; i++){
将可行解拓展一步;
backtracking(depth+1);
回退一步;
}
}
}
还是有难度的