字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。
示例1:
输入:"aabcccccaaa"
输出:"a2b1c5a3"
示例2:
输入:"abbccd"
输出:"abbccd"
解释:"abbccd"压缩后为"a1b2c2d1",比原字符串长度更长。
提示:
字符串长度在[0, 50000]范围内。
解题思路
1.把字符串变成字符数组,定义一个字符出现的次数,初始为1。
2.然后对比相邻的两个字符串是否相等,相等则次数+1,不相等则把字符和次数拼接到目标的字符串后面。
3.最后再把最后出现的字符拼接在最后。
4.比较目标字符串和输入的字符串的长度,选择短的输出即可。
class Solution {
public String compressString(String S) {
//字符串长度小于3的情况,直接返回原字符串
if (S.length() < 3) return S;
char[] chars = S.toCharArray();
StringBuilder resultStr = new StringBuilder();
//计数
int count = 1;
//从下标第二位开始
for (int i = 1; i < chars.length; i++) {
//和前一位进行比较,如果相等,计数+1
if (chars[i - 1] == chars[i]) {
count++;
} else {
//如果不想等,加到结果字符串里面,字符+出现的次数
resultStr.append(chars[i - 1]).append(count);
//初始化计数器为1
count = 1;
}
//如果最后一个字符,就直接加到最后,加上出现的次数
if (i == chars.length - 1) {
resultStr.append(chars[i]).append(count);
}
}
//再比较目标字符的长度和原字符的长度,取短的
return resultStr.length() >= S.length() ? S : resultStr.toString();
}
}
class Solution {
public String compressString(String S) {
if (S == null || S.length() < 2) return S;//null、""、以及一个字符的情况直接返回
int orignLen = S.length(), begin = 0, end = 1;
StringBuilder sb = new StringBuilder();
while (true) {
if (end == orignLen) {//当end等于S的长度时,结束
//避免用类似sb.append(S.charAt(begin)).append(end - begin);这样的写法,我试了下时间直接在原来基础上增加了2ms!!!
sb.append(S.charAt(begin));
sb.append(end - begin);
break;
} else if (S.charAt(end) == S.charAt(begin)) {//如果相等,那么扩大区间,即end下标右移
end++;
} else {//如果不等,说明这个区间已经结束,那么将begin下标位置字符以及区间长度添加到sb
sb.append(S.charAt(begin));
sb.append(end - begin);
begin = end++;//将新区间起始值begin设为end,同时end自增
}
}
return sb.length() < orignLen ? sb.toString() : S;//判断决定返回值
}
}
class Solution {
public String compressString(String S) {
if (S == null || S.length() <= 2) {//如果S的长度<=2 格式化的字符串一定不会比原字符串短
return S;
}
StringBuilder sb = new StringBuilder();
char[] s = S.toCharArray();//转换成char数组要比字符串索引查找要快一点
for(int i = 0;i<S.length();++i){
int count = 0;//计数
char a = s[i];//查找当前循环字符
while(i<S.length()&&a == s[i]){//防止索引越界判断是否和目标字符串相等
count++;
++i;//继续遍历下一个字符
}
i--;//上一次循环多加了一次,所以需要--
sb.append(a);
sb.append(count);
}
return sb.length()<S.length() ? sb.toString() : S;
}
}