- Interview Questions
- /
- Problems
- /
- String Compression
String Compression
Shrink a character array by replacing each run of repeated characters with the character and its count. A two-pointer exercise in reading and writing the same array. Solve it below in Python or JavaScript, then read the walkthrough.
Problem
You're given an array of single characters chars. Compress it by processing each run of consecutive equal characters:
- A run of length 1 becomes just the character.
- A longer run becomes the character followed by its length, with each digit of the length as its own array element. A run of 12
"m"s becomes["m", "1", "2"].
Return the compressed array.
The classic version of this problem asks you to write the result into chars itself using O(1) extra space and return the new length. Here you return the compressed characters so they can be checked directly, but try to build them with the same in-place technique: the walkthrough shows how.
Example 1
- Input
- chars = ["x", "x", "x", "y", "z", "z"]
- Output
- ["x", "3", "y", "z", "2"]
Three x's become "x3", the lone y stays "y", and two z's become "z2".
Example 2
- Input
- chars = ["q"]
- Output
- ["q"]
A single character has nothing to compress.
Example 3
- Input
- chars = ["m", "m", "m", "m", "m", "m", "m", "m", "m", "m", "m", "m", "n"]
- Output
- ["m", "1", "2", "n"]
A run of 12 writes two digit characters, "1" and "2".
Constraints
- 1 ≤ chars.length ≤ 2000
- Each chars[i] is a lowercase or uppercase letter, a digit, or a symbol.
Practice
Runs 12 tests in your browser. Python loads on the first run (about 6 MB, then cached). Press ⌘/Ctrl + Enter to run.
Get asked String Compression in a real interview?
Interview Solver gives you a working solution live, during your actual coding interview. Invisible to screensharing.
How to solve String Compression
Pattern: Read and write pointers
The output is never longer than the input. A run of length 1 writes one character; a run of length 2 writes two; a run of length 10 writes three. So as you scan left to right, the place you're writing can never get ahead of the place you're reading. That means you can compress into the same array you're reading from without overwriting anything you still need.
Use two pointers. read finds the end of the current run; write marks where the next compressed character goes. For each run, write the character, then, if the run is longer than one, write the digits of its length. When the scan ends, the first write slots hold the answer.
Approach 1: Build a new string or list
Scan the runs and append the character and its count to a fresh output list. Clear and correct, but uses O(n) extra memory, which the in-place version of the problem rules out.
Time O(n) · Space O(n)
Approach 2: In place with read and write pointers
Keep write = 0 and read = 0. While read < n:
- Remember
ch = chars[read]and advancereaduntilchars[read] != ch. The run length is the distance moved. - Set
chars[write] = chand advancewrite. - If the run length is more than 1, write each digit of
str(length)atwrite, advancing it each time.
The answer is the first write elements (the in-place version returns write as the new length). This solution returns chars[:write].
Time O(n) · Space O(1) extra
| Approach | Time | Space |
|---|---|---|
| Build a new string or list | O(n) | O(n) |
| In place with read and write pointers | O(n) | O(1) extra |
Solution code
Try the practice editor first. Both solutions pass every test above.
String Compression solution in Python
def compress(chars: list[str]) -> list[str]:
write = read = 0
n = len(chars)
while read < n:
ch = chars[read]
start = read
while read < n and chars[read] == ch:
read += 1
chars[write] = ch
write += 1
length = read - start
if length > 1:
for digit in str(length):
chars[write] = digit
write += 1
return chars[:write]String Compression solution in JavaScript
function compress(chars) {
let write = 0;
let read = 0;
const n = chars.length;
while (read < n) {
const ch = chars[read];
const start = read;
while (read < n && chars[read] === ch) read++;
chars[write++] = ch;
const length = read - start;
if (length > 1) {
for (const digit of String(length)) chars[write++] = digit;
}
}
return chars.slice(0, write);
}Common mistakes
- Writing the count for runs of length 1, which turns "abc" into "a1b1c1".
- Writing a multi-digit count as a single element like "12" instead of "1" and "2".
- Forgetting to flush the last run when the loop compares each character to the next one.
- Merging non-adjacent runs of the same character. "aabaa" has two separate runs of a.
What interviewers look for
Point out the reason in-place writing is safe before you write the loop: the compressed form of any run is at most as long as the run, so write never passes read. That one sentence is what interviewers want to hear, because it's the difference between a guess and a proof.
Test out loud with a run of length 1, a run of exactly 10 (two digits), and a last run that ends at the array boundary.
Follow-up questions
How would you decompress the result?
Read a character, then read any digits that follow and parse them as the count (default 1), and write the character that many times. Decompression usually needs a new buffer, because the output can be longer than the input.
What if the characters themselves can be digits?
Then the compressed form is ambiguous to decode: ["1", "3"] could mean "13" or three 1s. A real encoding would always write the count, or use an escape character or a fixed-width length.
What if you only want to compress when it actually saves space?
Do one counting pass first to compute the compressed length, and only rewrite if it is shorter than the original. Both passes are O(n).
Companies that ask String Compression
String Compression is tagged by 140 companies in our interview dataset. The score shows how often it comes up at each company.
- Fireeye100%
- Dicks Sporting Goods100%
- Allstate100%
- Crowdstrike100%
- Godaddy100%
- Samcart95%
- Peraton95%
- Yelp94.2%
- Everbridge93%
- Expedia91.4%
- Salesforce88.1%
- West Monroe88%
- Rakuten88%
- Rocket Software87%
- Goat Group86%
- Bairesdev86%
- Life36085%
- Zoominfo85%
- Clever84%
- Trend Micro84%
- Ihs Markit84%
- Servicenow83.8%
- Credit Karma83%
- Quantcast83%
and 116 more.
Practice next
Get live help in the real interview
Working solutions in real time during your actual interview. Invisible to screensharing.
Start Free TrialNo credit card required