首页 > 代码库 > 字符串的组合个数

字符串的组合个数

有一个MAP,KEY从a到z,对应的VALUE从1到26,比如:

a = 1

b = 2

...

z = 26,对于一个数字字符串"11",可以由"aa"对应的数字组合,也可以由"k"对应的数字代表,对应组合的个数记为2;同样,比如"111"对应的组合个数是3,分别是"aaa", "ka", "ak"。

给定一个数字数组,计算对应的组合个数。

 

解答:对于一个字符串,定义f(x)为前x个字符的组合个数,那么:

f(x) = f(x-2)               if 最后一个数字是‘0‘

      = f(x-1)               else if (倒数第二个数字是‘0‘ || 最后两个数大于"26")

      = f(x-1)+f(x-2)     else

int last2num(char* arr, int len){    assert(arr != NULL && len >= 2);    int num = (arr[len-2]-0)*10 + (arr[len-1]-0);    if (num <= 26)        return 2;    else        return 1;}int countKind(char* arr, int len){    if (arr == NULL || len <= 0)        return 0;    if (len == 1)        return 1;    if (len == 2)    {        if (arr[len-1] == 0 || last2num(arr, len) > 26)            return 1;        else             return 2;    }    if (arr[len-1] == 0)        return countKind(arr, len-2);    else if (arr[len-2] == 0 || last2num(arr, len) > 26)        return countKind(arr, len-1);    else        return countKind(arr, len-1) + countKind(arr, len-2);}

另一种写法:

上面用的递归,countKind有重复计算,一种方法是把计算过的保存在一个数组里,计算是查一下,如果算过,直接返回结果;另一种方法是从0开始顺序计算,代码如下:

int last2num(char* arr, int len){    assert(arr != NULL && len >= 2);    return 10*(arr[len-2]-0) + (arr[len-1]-0);}int countKind(char* arr, int len){    if (arr == NULL || len <= 0)        return 0;    if (len == 1)        return 1;    else if (len == 2)    {        if (arr[len-1] == 0 || last2num(arr, len) > 26)            return 1;        else            return 2;    }    int cnt[len+1];    cnt[0] = 0;    cnt[1] = 1;    if (arr[1] == 0  || last2num(arr, 2) > 26)        cnt[2] = 1;    else        cnt[2] = 2;    for (int i = 3; i < len; i++)    {        if (arr[i-1] == 0)            arr[i] = arr[i-2];        else if (arr[i-2] == 0 || last2num(arr, 2) > 26)            arr[i] = arr[i-1];        else            arr[i] = arr[i-1] + arr[i-2];    }    return arr[len];}

长度等于2的单独计算是必要的,为了解决类似"70"这样的case。

字符串的组合个数