原题传送门
首先我们来分析一下解决本题所需要的思路
map
这个键值对的结构,但是认真查看题目本身的话却发现我们不可以用这种结构输入:“aabcccccaaa”
输出:“a2b1c5a3”
map
的这种结构我们是不能使用unordered_map<char, int> count
for(char c : S)
{
count[c]++;
}
接下去就来看看下面的两种做法
ch
首先保存下第一个字符,后面遍历的时候再做更新char ch = S[0];
cnt
ch
是相同的话,计数器cnt
就去做一个累加,如果不相同的话,我们就可以去拼接字符串了,ch
即为当前所需要统计的字符,cnt
即为这个字符所出现的次数,不过我们要使用到C++里的一个库函数叫做 to_string ,不清楚的力友可以先去了解一下string compressStr = "";
for(int i = 1;i < sz; ++i)
{
if(S[i] == ch){
cnt++; // 如果当前所遍历到的字符与需统计字符相同的话,则计数器 + 1
}else{
compressStr += ch + to_string(cnt);
ch = S[i];
cnt = 1;
}
}
// 最后在遍历结束后添加最后一个字符的统计结果
compressStr += ch + to_string(cnt);
return compressStr.size() >= sz ? S : compressStr;
代码展示:
class Solution {
public:
string compressString(string S) {
int sz = S.size();
if(sz == 0)
return S; // 如果是空串的话,则返回自己本身
string compressStr = "";
int cnt = 1; // 统计每一个字符个数
char ch = S[0]; // 记录当前所要统计的字符
// 循环直接从1开始即可,第一个字符一定算一个
for(int i = 1;i < sz; ++i)
{
if(S[i] == ch){
cnt++; // 如果当前所遍历到的字符与需统计字符相同的话,则计数器 + 1
}else{
compressStr += ch + to_string(cnt);
ch = S[i];
cnt = 1;
}
}
// 最后在遍历结束后添加最后一个字符的统计结果
compressStr += ch + to_string(cnt);
// 三目运算符:若是压缩后的字符串长度 >= 原字符串的长度,则返回原串
return compressStr.size() >= sz ? S : compressStr;
}
};
最后展示一下AC后的结果
接下去要介绍的就是另一种解法,此解法来自 K神 很是巧妙,力友可以学习一下这种解法
总体思路概述:
i
和j
指向当前字符串的首位,然后让指针j
不断地先后遍历,比较 s[i] 和 s[j] 的的字符是否相同,若是相同的话则让j
继续后移,直到二者不相同为止。i
移动到j
的位置来即可,因为二者不相同后j
一定指向了一个新的字符然后我们就根据 示例1 来分布细述一下
j++
,i
不动j++
j - i
就可以计算得到,那么此时就可以将这结果追加到压缩后的字符串中了。接下去便是更新指针i
的位置到j
这里来,进行下一个字符串个数的统计j - i
可以算出其出现了5次,继续拼接到压缩串compressStr中代码展示:
class Solution {
public:
string compressString(string S) {
if(S.size() == 0) return S;
int i = 0, j = 0;
string compressStr = "";
while(j < S.size())
{
// 持续比较双指针上的位置,直到不相同为为止
while(S[i] == S[j]){
j++;
}
compressStr += S[i];
compressStr += to_string(j - i);
i = j; // i换位到新字符的位置
}
return compressStr.size() >= S.size() ? S : compressStr;
}
};
最后从提交的结果就可以看出效率提升了不少 ↑
认真看完上面这个例子后,其他的示例相信你一定也能推敲出来