版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sd4567855/article/details/86470818
day19, 压缩字符串
题目来源:leetcode
给定一组字符,使用原地算法将其压缩。
压缩后的长度必须始终小于或等于原数组长度。
数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。
在完成原地修改输入数组后,返回数组的新长度。
示例 1:
输入:
[“a”,“a”,“b”,“b”,“c”,“c”,“c”]
输出:
返回6,输入数组的前6个字符应该是:[“a”,“2”,“b”,“2”,“c”,“3”]
说明:
"aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。
示例 2:
输入:
[“a”]
输出:
返回1,输入数组的前1个字符应该是:[“a”]
说明:
没有任何字符串被替代。
示例 3:
输入:
[“a”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”,“b”]
输出:
返回4,输入数组的前4个字符应该是:[“a”,“b”,“1”,“2”]。
说明:
由于字符"a"不重复,所以不会被压缩。"bbbbbbbbbbbb"被“b12”替代。
注意每个数字在数组中都有它自己的位置。
注意:所有字符都有一个ASCII值在[35, 126]区间内。
解答:这道题思路很简单:遍历统计连续相同的字符数量,并在相同字符子序列中的第一个字符后面输出写入数量。
但是由于只允许使用原地算法,造成处理有些麻烦,注意几个坑。第一处:当遍历完之后要单独处理最后一个连续相同的字符子序列。第二处:把某个字符数量写入时,首先要转换成不会出现的ASCII码,否则之后删除原数组中重复元素时候会有些麻烦。
代码:
int digit( int n){
int num = 0;
while( n){
num++;
n/=10;
}
return num;
}
int compress(vector<char>& chars) {
if( chars.size() == 0)
return 0;
int sum_now = 1;
int sum = 0;
for( int i = 1; i < chars.size(); i++)
if( chars[i-1] == chars[i])
sum_now++;
else{
if( sum_now == 1)
sum += 1, sum_now = 1;
else{
sum += 1 + digit(sum_now);
int num = sum_now;
for( int j = i - 1, k = 0; k < digit(sum_now); k++){
chars[j] = num % 10 + 10;
num/=10;
j--;
}
sum_now = 1;
}
}
if( sum_now == 1)
sum += 1, sum_now = 1;
else{
sum += 1 + digit(sum_now);
int num = sum_now;
for( int j = chars.size() - 1, k = 0; k < digit(sum_now); k++){
chars[j] = num % 10 + 10;
num/=10;
j--;
}
sum_now = 1;
}
for( int i = chars.size() - 1; i > 0 ; i--)
if( chars[i] > 30 && chars[i-1] == chars[i])
chars[ i] = 33;
for( int i = chars.size() - 1; i > 0 ; i--)
if( chars[i] <= 30)
chars[ i] = chars[i] - 10 + '0';
for( int i = 0, k = 0; i< chars.size(); i++)
if( chars[i] == 33)
k++;
else
chars[i-k] = chars[i];
return sum;
}
运行结果: