Medium
题目描述
给你一个字符数组 chars,请使用下述算法压缩:
从空字符串 s 开始。对于 chars 中的每组 连续重复字符:
- 如果这一组长度为 1 ,则将字符追加到
s中。 - 否则,需要向
s追加字符,后跟这一组的长度。
压缩后得到的字符串 s 不应该直接返回,需要转储到字符数组 chars 中。需要注意的是,如果组长度为 10 或 10 以上,则在 chars 数组中会被拆分为多个字符。
请在修改完输入数组后,返回该数组的新长度。
你必须设计并实现一个只使用常量额外空间的算法来解决此问题。
注意: 超出返回长度的数组元素不重要,可以忽略。
示例 1:
输入:chars = ["a","a","b","b","c","c","c"]
输出:6
解释:groups 是 ["aa", "bb", "ccc"]。压缩后变为 "a2b2c3"。
示例 2:
输入:chars = ["a"]
输出:1
解释:唯一的组是 "a",它保持未压缩,因为它是一个字符。
示例 3:
输入:chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
输出:4
解释:groups 是 ["a", "bbbbbbbbbbbb"]。压缩后变为 "ab12"。
提示:
1 <= chars.length <= 2000chars[i]可以是小写英文字母、大写英文字母、数字或符号
解题思路
这道题要求我们对字符数组进行原地压缩,核心思路是使用双指针技巧。
解题思路:
- 双指针遍历:使用读指针
read遍历原数组,写指针write记录压缩后的位置 - 分组统计:对于每个字符,统计连续出现的次数
- 原地写入:将字符和计数(如果大于1)写入到
write位置 - 数字处理:当计数大于等于10时,需要将数字拆分成多个字符
算法步骤:
- 初始化读写指针都为0
- 遍历数组,对每个字符进行分组:
- 记录当前字符并统计连续出现次数
- 将字符写入write位置
- 如果计数大于1,将计数转换为字符串并逐位写入
- 返回最终的写指针位置
关键点:
- 计数为1时只写字符,不写数字
- 计数大于等于10时需要逐位写入数字
- 原地操作,空间复杂度O(1)
这种方法时间复杂度为O(n),空间复杂度为O(1),是最优解法。
代码实现
class Solution {
public:
int compress(vector<char>& chars) {
int write = 0, read = 0;
int n = chars.size();
while (read < n) {
char currentChar = chars[read];
int count = 0;
// 统计连续相同字符的数量
while (read < n && chars[read] == currentChar) {
read++;
count++;
}
// 写入字符
chars[write++] = currentChar;
// 如果count > 1,写入数字
if (count > 1) {
string countStr = to_string(count);
for (char c : countStr) {
chars[write++] = c;
}
}
}
return write;
}
};
class Solution:
def compress(self, chars: List[str]) -> int:
write = 0
read = 0
n = len(chars)
while read < n:
current_char = chars[read]
count = 0
# 统计连续相同字符的数量
while read < n and chars[read] == current_char:
read += 1
count += 1
# 写入字符
chars[write] = current_char
write += 1
# 如果count > 1,写入数字
if count > 1:
count_str = str(count)
for c in count_str:
chars[write] = c
write += 1
return write
public class Solution {
public int Compress(char[] chars) {
int write = 0, read = 0;
int n = chars.Length;
while (read < n) {
char currentChar = chars[read];
int count = 0;
// 统计连续相同字符的数量
while (read < n && chars[read] == currentChar) {
read++;
count++;
}
// 写入字符
chars[write++] = currentChar;
// 如果count > 1,写入数字
if (count > 1) {
string countStr = count.ToString();
foreach (char c in countStr) {
chars[write++] = c;
}
}
}
return write;
}
}
var compress = function(chars) {
let write = 0, read = 0;
const n = chars.length;
while (read < n) {
const currentChar = chars[read];
let count = 0;
// 统计连续相同字符的数量
while (read < n && chars[read]
复杂度分析
| 复杂度类型 | 值 | 说明 |
|---|---|---|
| 时间复杂度 | O(n) | 遍历一遍字符数组,每个字符访问一次 |
| 空间复杂度 | O(1) | 只使用常量额外空间,原地修改数组 |
相关题目
. Count and Say (Medium)
. Encode and Decode Strings (Medium)
. String Compression III (Medium)
. Better Compression of String (Medium)