字符串压缩
难度:
标签:
题目描述
Implement a method to perform basic string compression using the counts of repeated characters. For example, the string aabcccccaaa would become a2blc5a3. If the "compressed" string would not become smaller than the original string, your method should return the original string. You can assume the string has only uppercase and lowercase letters (a - z).
Example 1:
Input: "aabcccccaaa" Output: "a2b1c5a3"
Example 2:
Input: "abbccd" Output: "abbccd" Explanation: The compressed string is "a1b2c2d1", which is longer than the original string.
Note:
0 <= S.length <= 50000
代码结果
运行时间: 26 ms, 内存: 16.1 MB
/*
* 思路:
* 1. 使用Java Stream API处理字符串。
* 2. 将字符串拆分为字符流,并使用Collectors.groupingBy统计每个字符的连续出现次数。
* 3. 构建压缩后的字符串。
* 4. 如果压缩后的字符串长度大于或等于原字符串长度,则返回原字符串。
*/
import java.util.stream.Collectors;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.IntStream;
public class StringCompressionStream {
public String compress(String s) {
if (s == null || s.length() == 0) return s;
List<Character> chars = s.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
StringBuilder compressed = new StringBuilder();
IntStream.range(0, chars.size()).forEach(i -> {
int count = 1;
while (i + 1 < chars.size() && chars.get(i).equals(chars.get(i + 1))) {
count++;
i++;
}
compressed.append(chars.get(i)).append(count);
});
return compressed.length() >= s.length() ? s : compressed.toString();
}
public static void main(String[] args) {
StringCompressionStream scs = new StringCompressionStream();
System.out.println(scs.compress("aabcccccaaa")); // 输出: a2b1c5a3
System.out.println(scs.compress("abbccd")); // 输出: abbccd
}
}
解释
方法:
该题解通过遍历字符串S,并计算每个字符连续出现的次数来构造压缩后的字符串。遍历过程中,用ch_prev记录前一个字符,用count记录该字符的连续出现次数。为了简化末尾字符的处理,给字符串S额外添加了一个不同的字符'@'作为结束标记。这样,当遇到新字符或结束字符'@'时,将前一个字符及其计数追加到结果字符串ret中。最后比较压缩后字符串的长度与原字符串的长度,如果压缩后没有变短,则返回原字符串。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在字符串'S'末尾添加'@'字符,这样做有什么特别的意义或优势?
▷🦆
如果字符串S中包含了'@'字符,这种方法添加'@'作为结束标记还会有效吗?
▷🦆
在比较压缩后的字符串长度和原字符串长度时,为什么选择在循环结束后比较,而不是在循环过程中就终止返回原字符串?
▷