String Compression

Compress runs of identical characters in place, writing the character followed by its count.

Medium
Time O(n) Space O(1)
LeetCode
4 min read
two-pointers string

Problem#

Given an array of characters, compress it in place: each run becomes the character followed by its run length (omit the length if it’s 1). Return the new length.

Examples#

  • ["a","a","b","b","c","c","c"]6 with prefix ["a","2","b","2","c","3"]
  • ["a"]1, ["a"]
  • ["a","b","b","b","b","b","b","b","b","b","b","b","b"]4 with ["a","b","1","2"]

Constraints#

  • 1 <= chars.length <= 2000.

Hints#

Hint 1
Write the character at the run start, then count, then emit each digit.

Approach#

Three indices: read i, write w, run-start j. Walk forward; at the end of each run (i == end-of-run), write the character at w, then if count > 1, write each decimal digit. Multi-digit counts are written most-significant-first via a small reverse trick (or by computing digits then reversing the just-written range).

Solution#

String Compression
class Solution {
public:
int compress(vector<char>& chars) {
int w = 0, i = 0, n = chars.size();
while (i < n) {
int j = i;
while (j < n && chars[j] == chars[i]) ++j;
chars[w++] = chars[i];
int count = j - i;
if (count > 1) {
int start = w;
while (count > 0) {
chars[w++] = '0' + (count % 10);
count /= 10;
}
reverse(chars.begin() + start, chars.begin() + w);
}
i = j;
}
return w;
}
};

Editorial#

In-place compression works because the compressed form is never longer than the source (the worst case n=1 writes 1 char; any run length ≥ 2 writes at most 1 + ceil(log10(count)) chars, bounded by 1 + len of run). The reverse handles multi-digit counts cleanly without a temporary buffer.

Complexity#

  • Time: O(n).
  • Space: O(1).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.