class Solution:
def compress(self, chars):
write = 0
read = 0
n = len(chars)
while read < n:
char = chars[read]
count = 0
# Count the number of occurrences of the current character
while read < n and chars[read] == char:
read += 1
count += 1
chars[write] = char
write += 1
if count > 1:
for c in str(count):
chars[write] = c
write += 1
return write
class Solution {
public:
int compress(vector<char>& chars) {
int write = 0, read = 0;
int n = chars.size();
while (read < n) {
char current = chars[read];
int count = 0;
while (read < n && chars[read] == current) {
read++;
count++;
}
chars[write++] = current;
if (count > 1) {
string cnt = to_string(count);
for (char c : cnt) {
chars[write++] = c;
}
}
}
return write;
}
};
class Solution {
public int compress(char[] chars) {
int write = 0, read = 0, n = chars.length;
while (read < n) {
char ch = chars[read];
int count = 0;
while (read < n && chars[read] == ch) {
read++;
count++;
}
chars[write++] = ch;
if (count > 1) {
String cnt = Integer.toString(count);
for (char c : cnt.toCharArray()) {
chars[write++] = c;
}
}
}
return write;
}
}
var compress = function(chars) {
let write = 0, read = 0;
const n = chars.length;
while (read < n) {
let char = chars[read];
let count = 0;
while (read < n && chars[read] === char) {
read++;
count++;
}
chars[write++] = char;
if (count > 1) {
let str = String(count);
for (let c of str) {
chars[write++] = c;
}
}
}
return write;
};
Given an array of characters chars
, compress it in-place. The compression algorithm works as follows: For each group of consecutive repeating characters in the array, replace the group with a single character followed by the number of times it appears (if more than once). The compression must be done using only the input array for storage (no extra arrays), and the function should return the new length of the array after compression.
chars
in-place and return the new length.
Example:
Input: ["a","a","b","b","c","c","c"]
Output: 6
, and the array becomes ["a","2","b","2","c","3"]
.
To solve this problem, we first consider the brute-force approach: scan through the array, count consecutive characters, and build a new array with the results. However, the problem requires us to do this in-place, meaning we cannot use extra space proportional to the input size.
The key insight is to use two pointers: one for reading through the array (read
), and one for writing the compressed characters (write
). As we encounter a run of the same character, we count how many times it appears, then write the character (and its count, if >1) back to the array at the write
position. This allows us to overwrite the input array as we go, using only constant extra space for counters and pointers.
By thinking in terms of "read" and "write" pointers, we avoid the need for extra storage and can meet the problem's constraints efficiently.
read
and write
, both starting at 0.
read
is less than the length of chars
, do the following:
read
while the next character is the same, incrementing a count
variable.write
position, then increment write
.count
is greater than 1, convert count
to a string and write each digit to the array, incrementing write
each time.write
pointer now indicates the new length of the compressed array.This approach ensures that we only use constant extra space (for pointers and counters), and all modifications happen in-place.
Let's use the sample input: ["a","a","b","b","c","c","c"]
.
read
scans two "a"s, so count=2
.write=0
. Then write "2" at write=1
.read
scans two "b"s, so count=2
.write=2
. Then write "2" at write=3
.read
scans three "c"s, so count=3
.write=4
. Then write "3" at write=5
.write
is now 6. The array is ["a","2","b","2","c","3"]
.
Each iteration compresses a group and writes the result in-place, overwriting the original array.
This makes the in-place two-pointer solution both efficient and scalable.
The string compression problem is elegantly solved using a two-pointer technique, allowing us to compress character groups in-place with constant extra space. By carefully tracking where to read and write in the array, we efficiently overwrite the input with its compressed form. The key insight is recognizing that a single pass, with careful pointer management, suffices to meet all constraints and optimize both time and space complexity.