LeetCode-简单-38-外观数列(C)
这题想把内存降低的话,一个很邪道的方法,是把结果长度遍历出来然后按需分配。
这个按需分配不是realloc,这个函数在LeetCode里面消耗内存很大,我也不清楚是这函数特性还是LeetCode特性。
题目
给定一个正整数 n ,输出外观数列的第 n 项。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
你可以将其视作是由递归公式定义的数字字符串序列:
countAndSay(1) = "1"
countAndSay(n) 是对 countAndSay(n-1) 的描述,然后转换成另一个数字字符串。
前五项如下:
- 1
- 11
- 21
- 1211
- 111221
第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"
要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。
例如,数字字符串 "3322251" 的描述如下图:
示例 1:
输入:n = 1
输出:"1"
解释:这是一个基本样例。
示例 2:
输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"
提示:
1 <= n <= 30
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-and-say
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
- 一个result存放递归(n)的描述字符串,一个say存放递归(n-1)的描述字符串。
- 从say的第2位开始循环,直到strlen(say)+1:
- 每次循环都判断该位与前位是否相同,不同就将result新增,相同就计数。
- 在result新增的部分,先增加相同数量,再增加相同的字符。
- 当循环到say的第strlen(say)+1时,直接添加result,不然会出错,因为say没有那么长。
- 减少内存消耗的话,可以将所有的情况分配的空间都遍历出来,就像倒数第四行被注释的代码一样。
- 不过效果和分段划分大小差不多,我测试了一下,switch代码和下面的if代码效果相似,都能0ms,6MB,所以为了显得我正常一点点,就用了if的。
switch(n){
case 2: resultLen=3; break;
case 3: resultLen=3; break;
case 4: resultLen=5; break;
case 5: resultLen=7; break;
case 6: resultLen=7; break;
case 7: resultLen=9; break;
case 8: resultLen=11; break;
case 9: resultLen=15; break;
case 10: resultLen=21; break;
case 11: resultLen=27; break;
case 12: resultLen=35; break;
case 13: resultLen=47; break;
case 14: resultLen=63; break;
case 15: resultLen=79; break;
case 16: resultLen=103; break;
case 17: resultLen=135; break;
case 18: resultLen=177; break;
case 19: resultLen=227; break;
case 20: resultLen=303; break;
case 21: resultLen=409; break;
case 22: resultLen=529; break;
case 23: resultLen=679; break;
case 24: resultLen=905; break;
case 25: resultLen=1183; break;
case 26: resultLen=1541; break;
case 27: resultLen=2013; break;
case 28: resultLen=2607; break;
case 29: resultLen=3411; break;
case 30: resultLen=4463; break;
}
代码
char * countAndSay(int n){
if(n==1){
return "1";
}
else{
int num=1, len, pos, resultPos=0, resultLen;
if(n<=15) resultLen=79;
else if(n<=20) resultLen=303;
else if(n<=25) resultLen=1183;
else if(n<=27) resultLen=2021;
else if(n<=30) resultLen=4463;
char* say = countAndSay(n-1);
char* result = (char*)malloc(resultLen);
result[0]='\0';
for(len = strlen(say), pos=1; pos<=len; pos++){
if(pos==len){
result[resultPos*2] = '0'+num;
result[resultPos*2+1] = say[pos-1];
result[resultPos*2+2] = '\0';
resultPos++;
}
else if(say[pos] == say[pos-1]){
num+=1;
}
else{
result[resultPos*2] = '0'+num;
result[resultPos*2+1] = say[pos-1];
result[resultPos*2+2] = '\0';
resultPos++;
num=1;
}
}
//printf("case %d: resultLen=%d; break;\n", n, strlen(result)+1);
return result;
}
}
共有 0 条评论