题解 | #压缩字符串(一)#
压缩字符串(一)
http://www.nowcoder.com/practice/c43a0d72d29941c1b65c857d8ac9047e
学习别人的优秀写法,能想到用log10(x)的真是人才!
用双指针,刚开始均指向第一个字母,然后开始比较,(每轮比较第一次比较的其实是同一个字母,第二次才是正式比较才决定要不要压缩)
如果后面指针所指元素和前面不同,说明前面字母只出现一次,那么在字符串中保留该字母,用新指针进行赋值。
如果后面指针所指元素和前面相同,说明需要压缩了,但先得找出该字母出现了几次,指针继续后移直到所指不一样,下标差值即使出现次数。
次数算出来之后,又有问题,因为不是直接赋值,次数是整型,字母是字符型,要赋值,只能赋2-9,两位数需要2个字符,三位数需要3个字符。
比起单独讨论二位数次数,三位数次数,四位数次数的情况,终于看到一个优秀人才用到了log10(x)来确定所需字符的个数
从后往前依次填入个位数,十位数,百位数等,当然,是字符型,不是整型
遍历完所有字母后,加上结束标志'\0'.
char* compressString(char* param ) {
if(param == NULL)
return NULL; //字符串为空的特殊情况单独处理
int i=0, j=0, k=0;
int len = strlen(param);
while(i<len){
for(j = i; j<len; j++) //一个前指针,一个后指针,刚开始指向同一个元素,每次while开始都是指同一个字母
if(param[j] != param[i]) //如果后指针与前指针指的不是同一个字母
break; //跳出for循环开始压缩该字母
int cnt = j - i; //j-i就是该字符连续出现的次数
param[k++] = param[i]; //先把字符保留,指针后移一位,开始讨论填入几的问题
if(cnt >1 && cnt < 10) //如果该字符连续出现次数为个位数
param[k++] = cnt + '0'; //那么只需要一位便可解决,
//因为是字符型,不是整型,所以次数要转化为字符型,加上字符0即可
else if(cnt >= 10){ //如果次数大于等于10,那就复杂了,可能是两位数,三位数,四位数等
//那么就需要用到2个,3个,4个字符来存储
int tmp = k + (int)log10(cnt); //用log可以算出是几位数,tmp是填入数字的最后一个下标
k = tmp + 1; // k 作为下一个字母的下标
while(cnt > 0){
param[tmp--] = cnt % 10 +'0'; //从个位数开始填,从低到高,从右往左
cnt = cnt / 10; //填完尾数就截断尾数,继续填下一位高位
}
}
i = j; //j是下个字母的下标,填完一个字母的次数后继续下一轮检查和压缩
}
param[k] = '\0'; //务必自己添加字符串结束标志
return param;
}