Editorial
Core insight
String Compression · Two Pointers
Core Insight for String Compression
The core insight for solving LeetCode 443 efficiently lies in the realization that the compressed version of any character group is always shorter than or equal in length to the original group (with the exception of single characters, which remain length 1).
Because the compressed data is generated sequentially and is generally shorter than the source data, we can safely overwrite the beginning of the array with the compressed result while we are still reading the rest of the array.
The algorithm relies on maintaining a strict invariant:
- Read Pointer (
i): Scans the array to determine the extent of the current group of identical characters. - Write Pointer (
write_index): Marks the position where the next piece of compressed data (character or digit) should be stored.
Visual Description:
Imagine the array as a tape. The read head moves forward rapidly, counting how many times a character repeats. Once the read head hits a different character, the write head (which is lagging behind) records the character and the count. The write head then advances. Because we process groups from left to right, the write head will never overtake the read head, preventing data corruption.

Deep dive
Full breakdown
Full reasoning, pitfalls, and implementation flow
LeetCode 443: String Compression Solution & Explanation
Problem Overview
TL;DR: Iterate through the array using a read pointer to identify groups of consecutive characters and a write pointer to overwrite the array in-place with the compressed format.
The String Compression problem requires performing Run-Length Encoding on a character array. The task is to replace consecutive repeating characters with the character itself followed by the count of repetitions. If a character appears only once, it is appended without a count. Crucially, this operation must be performed in-place on the input array chars, and the algorithm must return the new length of the modified array.
This is a popular interview question (LeetCode 443) that tests a candidate's ability to manipulate array pointers efficiently under strict space constraints.
Brute Force Approach for String Compression
A naive approach to solving String Compression involves using auxiliary space to build the result.
- Create a new empty string or list
result. - Iterate through the input
charsarray. - Count consecutive occurrences of each character.
- Append the character and its count (if greater than 1) to
result. - Finally, copy the contents of
resultback into the originalcharsarray and return the length.
Pseudo-code:
function compress(chars):
string res = ""
i = 0
while i < length(chars):
char c = chars[i]
count = 0
while i < length(chars) and chars[i] == c:
count++
i++
res += c
if count > 1:
res += string(count)
for j from 0 to length(res):
chars[j] = res[j]
return length(res)Why this fails: While this solution is logically correct and runs in linear time , it has a Space Complexity of because it creates a separate string/list proportional to the size of the input. The problem explicitly constraints the solution to use O(1) constant extra space. Therefore, a brute force approach that allocates new storage for the compressed string is suboptimal and may be rejected in an interview setting.
Algorithm Strategy: Two Pointers - In-place Array Modification
To implement this strategy for String Compression, we follow these rules:
- Initialize a
writepointer at index 0. - Use a
readpointer (often the loop variablei) to iterate through the array. - For every unique character group encountered by
read:- Identify the start and end of the consecutive group to calculate the
count. - Write the character itself to
chars[write]and incrementwrite. - If the
countis greater than 1, convert the integercountinto string format. - Iterate through the digits of the count string, writing each digit to
chars[write]and incrementingwriteeach time.
- Identify the start and end of the consecutive group to calculate the
- After the loop finishes, the
writepointer represents the new length of the compressed array.
This approach ensures we satisfy the O(1) space constraint by utilizing the input array itself as the storage buffer.
Execution Flow
Let's trace the algorithm with chars = ["a", "a", "b", "b", "c", "c", "c"]:
- Initialization:
i = 0,write = 0. - First Group ('a'):
ipoints to first 'a'. We scan forward until we hit 'b' or end of array.- We find 2 'a's.
count = 2. - Write 'a' at
chars[0].writebecomes 1. count > 1, so we convert 2 to "2". Write '2' atchars[1].writebecomes 2.- Move
ipast the group of 'a's.
- Second Group ('b'):
ipoints to first 'b'. Scan forward.- We find 2 'b's.
count = 2. - Write 'b' at
chars[2].writebecomes 3. count > 1, write '2' atchars[3].writebecomes 4.- Move
ipast the group of 'b's.
- Third Group ('c'):
ipoints to first 'c'. Scan forward.- We find 3 'c's.
count = 3. - Write 'c' at
chars[4].writebecomes 5. count > 1, write '3' atchars[5].writebecomes 6.- Move
ipast the group of 'c's.
- Termination:
ihas reached the end of the array. Returnwrite(which is 6).
The array effectively becomes ["a", "2", "b", "2", "c", "3", "c"], but since we return length 6, the consumer only sees the valid prefix.
Proof of Correctness
The correctness relies on the fact that write <= read at all times.
- Case 1 (Single Character): If a group has length 1 (e.g.,
['x']), we write 'x' and advancewriteby 1. Thereadpointer also advances by 1. No overwrite occurs. - Case 2 (Multiple Characters): If a group has length , we write 1 character plus digits, where is the number of digits in . Since , the compressed length is always less than or equal to for .
- Example:
aa(len 2) ->a2(len 2). - Example:
aaaaaaaaaaaa(len 12) ->a12(len 3).
- Example:
Since the compressed form never exceeds the original length of the group, the write pointer never overtakes the start of the next unprocessed group. Thus, we never overwrite data that hasn't been read yet.
Pattern Reuse Notes
The Two Pointers - In-place Array Modification pattern is fundamental for optimizing space in array problems.
- LeetCode 26: Remove Duplicates from Sorted Array - Uses the same logic: a read pointer finds unique elements, and a write pointer builds the unique prefix.
- LeetCode 27: Remove Element - Skips specific values with the read pointer, compacting valid values with the write pointer.
- LeetCode 75: Sort Colors - A variation using three pointers to partition the array in-place.
- LeetCode 80: Remove Duplicates from Sorted Array II - Similar to problem 26 but allows a specific number of duplicates, requiring slightly more complex logic for the write pointer.
Feynman coach · Before you peek at the code
Can you explain the core insight in your own words?
If you can explain it before reading code, you’re far more likely to recall it under interview pressure.
Reference Implementation
C++ Solution for LeetCode 443
1#include <vector>
2#include <string>
3
4class Solution {
5public:
6 int compress(std::vector<char>& chars) {
7 int write = 0;
8 int i = 0;
9
10 while (i < chars.size()) {
11 char currentChar = chars[i];
12 int count = 0;
13
14 // Count consecutive characters
15 while (i < chars.size() && chars[i] == currentChar) {
16 i++;
17 count++;
18 }
19
20 // Write the character
21 chars[write++] = currentChar;
22
23 // If count > 1, write the digits
24 if (count > 1) {
25 std::string countStr = std::to_string(count);
26 for (char c : countStr) {
27 chars[write++] = c;
28 }
29 }
30 }
31
32 return write;
33 }
34};Java Solution for LeetCode 443
1class Solution {
2 public int compress(char[] chars) {
3 int write = 0;
4 int i = 0;
5
6 while (i < chars.length) {
7 char currentChar = chars[i];
8 int count = 0;
9
10 // Count consecutive characters
11 while (i < chars.length && chars[i] == currentChar) {
12 i++;
13 count++;
14 }
15
16 // Write the character
17 chars[write++] = currentChar;
18
19 // If count > 1, write the digits
20 if (count > 1) {
21 String countStr = Integer.toString(count);
22 for (char c : countStr.toCharArray()) {
23 chars[write++] = c;
24 }
25 }
26 }
27
28 return write;
29 }
30}Python Solution for LeetCode 443
1class Solution:
2 def compress(self, chars: List[str]) -> int:
3 write = 0
4 i = 0
5
6 while i < len(chars):
7 current_char = chars[i]
8 count = 0
9
10 # Count consecutive characters
11 while i < len(chars) and chars[i] == current_char:
12 i += 1
13 count += 1
14
15 # Write the character
16 chars[write] = current_char
17 write += 1
18
19 # If count > 1, write the digits
20 if count > 1:
21 for digit in str(count):
22 chars[write] = digit
23 write += 1
24
25 return write