443. String Compression
Problem Description
Given an array of characters chars, compress it using the following algorithm:
Begin with an empty string s. For each group of consecutive repeating characters in chars:
- If the group's length is 1, append the character to
s. - Otherwise, append the character followed by the group's length.
The compressed string s should not be returned separately, but instead, be stored in the input character array chars. Note that group lengths that are 10 or longer will be split into multiple characters in chars.
After you are done modifying the input array, return the new length of the array.
Example 1:
Input: chars = ["a","a","b","b","c","c","c"]
Output: Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"]
Explanation: The groups are "aa", "bb", and "ccc". This compresses to "a2b2c3".
Example 2:
Input: chars = ["a"]
Output: Return 1, and the first character of the input array should be: ["a"]
Explanation: The only group is "a", which remains uncompressed since it's a single character.
Example 3:
Input: chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
Output: Return 4, and the first 4 characters of the input array should be: ["a","b","1","2"]
Explanation: The groups are "a" and "bbbbbbbbbbbbb". This compresses to "ab12".
Constraints:
1 <= chars.length <= 2000chars[i]is a lowercase English letter, uppercase English letter, digit, or symbol.
Solution
Python Solution
class Solution:
def compress(self, chars: List[str]) -> int:
write = 0 # Position to write compressed characters
anchor = 0 # Start of the current group
for read, char in enumerate(chars):
# If we're at the end of the array or a different character
if read + 1 == len(chars) or chars[read + 1] != char:
chars[write] = chars[anchor] # Write the character
write += 1
if read > anchor: # If there was more than one character
count = read - anchor + 1
# Convert the count to string and write each digit
for digit in str(count):
chars[write] = digit
write += 1
anchor = read + 1 # Move anchor to start of next group
return write
Time Complexity: O(n)
Where n is the length of the input array.
Space Complexity: O(1)
Only using constant extra space.
Java Solution
class Solution {
public int compress(char[] chars) {
int write = 0; // Position to write compressed characters
int anchor = 0; // Start of the current group
for (int read = 0; read < chars.length; read++) {
// If we're at the end of the array or a different character
if (read + 1 == chars.length || chars[read + 1] != chars[read]) {
chars[write++] = chars[anchor]; // Write the character
if (read > anchor) { // If there was more than one character
String count = String.valueOf(read - anchor + 1);
// Write each digit of the count
for (char c : count.toCharArray()) {
chars[write++] = c;
}
}
anchor = read + 1; // Move anchor to start of next group
}
}
return write;
}
}
Time Complexity: O(n)
Where n is the length of the input array.
Space Complexity: O(1)
Only using constant extra space.
C++ Solution
class Solution {
public:
int compress(vector& chars) {
int write = 0; // Position to write compressed characters
int anchor = 0; // Start of the current group
for (int read = 0; read < chars.size(); read++) {
// If we're at the end of the array or a different character
if (read + 1 == chars.size() || chars[read + 1] != chars[read]) {
chars[write++] = chars[anchor]; // Write the character
if (read > anchor) { // If there was more than one character
string count = to_string(read - anchor + 1);
// Write each digit of the count
for (char c : count) {
chars[write++] = c;
}
}
anchor = read + 1; // Move anchor to start of next group
}
}
return write;
}
};
Time Complexity: O(n)
Where n is the length of the input array.
Space Complexity: O(1)
Only using constant extra space.
JavaScript Solution
/**
* @param {character[]} chars
* @return {number}
*/
var compress = function(chars) {
let write = 0; // Position to write compressed characters
let anchor = 0; // Start of the current group
for (let read = 0; read < chars.length; read++) {
// If we're at the end of the array or a different character
if (read + 1 === chars.length || chars[read + 1] !== chars[read]) {
chars[write++] = chars[anchor]; // Write the character
if (read > anchor) { // If there was more than one character
const count = String(read - anchor + 1);
// Write each digit of the count
for (const digit of count) {
chars[write++] = digit;
}
}
anchor = read + 1; // Move anchor to start of next group
}
}
return write;
};
Time Complexity: O(n)
Where n is the length of the input array.
Space Complexity: O(1)
Only using constant extra space.
C# Solution
public class Solution {
public int Compress(char[] chars) {
int write = 0; // Position to write compressed characters
int anchor = 0; // Start of the current group
for (int read = 0; read < chars.Length; read++) {
// If we're at the end of the array or a different character
if (read + 1 == chars.Length || chars[read + 1] != chars[read]) {
chars[write++] = chars[anchor]; // Write the character
if (read > anchor) { // If there was more than one character
string count = (read - anchor + 1).ToString();
// Write each digit of the count
foreach (char c in count) {
chars[write++] = c;
}
}
anchor = read + 1; // Move anchor to start of next group
}
}
return write;
}
}
Time Complexity: O(n)
Where n is the length of the input array.
Space Complexity: O(1)
Only using constant extra space.
Approach Explanation
The solution uses a two-pointer approach with read and write pointers:
- Key Insights:
- Two-pointer technique
- In-place modification
- Group counting
- Character handling
- Algorithm Steps:
- Track positions
- Count groups
- Write characters
- Handle counts
Implementation Details:
- Position tracking
- Group detection
- Count conversion
- Array modification
Optimization Insights:
- In-place update
- Single pass
- Memory efficiency
- Early termination
Edge Cases:
- Single character
- Long sequences
- No repeats
- All repeats