Skip to content

Commit bc47995

Browse files
committed
feat: add string compression solution
1 parent fa9a08d commit bc47995

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@
88
| 2 | [Move Zeroes](https://leetcode.com/problems/move-zeroes/) | [TypeScript](https://github.com/sandrig/leetcode/blob/master/typescript/src/moveZeroes/README.md) | _O(n)_ | _O(1)_ | Array, Two Pointers |
99
| 3 | [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) | [TypeScript](https://github.com/sandrig/leetcode/blob/master/typescript/src/validPalindrome/README.md) | _O(n)_ | _O(n)_ | String, Two Pointers |
1010
| 4 | [Summary Ranges](https://leetcode.com/problems/summary-ranges/) | [TypeScript](https://github.com/sandrig/leetcode/blob/master/typescript/src/summaryRanges/README.md) | _O(n)_ | _O(n)_ | Array |
11+
12+
## Medium
13+
14+
| # | Problem | Solution | Time | Space | Tag |
15+
| --- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------ | ------ | -------------------- |
16+
| 1 | [String Compression](https://leetcode.com/problems/string-compression/) | [TypeScript](https://github.com/sandrig/leetcode/blob/master/typescript/src/stringCompression/README.md) | _O(n)_ | _O(n)_ | Two Pointers, String |
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# [String Compression](https://leetcode.com/problems/string-compression/)
2+
3+
## Description
4+
5+
Given an array of characters **chars**, compress it using the following algorithm:
6+
7+
Begin with an empty string **s**. For each group of consecutive repeating characters in **chars**:
8+
9+
- If the group's length is **1**, append the character to **s**.
10+
- Otherwise, append the character followed by the group's length.
11+
12+
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**.
13+
14+
After you are done modifying the input array, return the new length of the array.
15+
16+
You must write an algorithm that uses only constant extra space.
17+
18+
**Example 1:**
19+
20+
```
21+
Input: chars = ["a","a","b","b","c","c","c"]
22+
Output: Return 6, and the first 6 characters of the input array should be: ["a","2","b","2","c","3"]
23+
Explanation: The groups are "aa", "bb", and "ccc". This compresses to "a2b2c3".
24+
```
25+
26+
**Example 2:**
27+
28+
```
29+
Input: chars = ["a"]
30+
Output: Return 1, and the first character of the input array should be: ["a"]
31+
Explanation: The only group is "a", which remains uncompressed since it's a single character.
32+
```
33+
34+
**Example 3:**
35+
36+
```
37+
Input: chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
38+
Output: Return 4, and the first 4 characters of the input array should be: ["a","b","1","2"].
39+
Explanation: The groups are "a" and "bbbbbbbbbbbb". This compresses to "ab12".
40+
```
41+
42+
## Solution
43+
44+
```typescript
45+
function compress(chars: string[]): number {
46+
let writeIndex = 0; // Index to write compressed characters
47+
let readIndex = 0; // Index to read source characters
48+
49+
while (readIndex < chars.length) {
50+
const currentChar = chars[readIndex];
51+
let count = 0;
52+
53+
// Counting the number of repeated characters
54+
while (readIndex < chars.length && chars[readIndex] === currentChar) {
55+
readIndex++;
56+
count++;
57+
}
58+
59+
// Write a compressed character
60+
chars[writeIndex] = currentChar;
61+
writeIndex++;
62+
63+
// If the character is repeated more than once, record the number of repetitions
64+
if (count > 1) {
65+
for (const digit of count.toString().split("")) {
66+
chars[writeIndex] = digit;
67+
writeIndex++;
68+
}
69+
}
70+
}
71+
72+
// Returning the new length of the compressed string
73+
return writeIndex;
74+
}
75+
```
76+
77+
## Complexity Analysis
78+
79+
- Time complexity: _O(n)_
80+
- Space complexity: _O(n)_
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { compress } from "./stringCompression";
2+
3+
describe("String Compression", () => {
4+
it("should compress the string with repeated characters", () => {
5+
const chars: string[] = ["a", "a", "b", "b", "c", "c", "c"];
6+
const compressedLength = compress(chars);
7+
expect(compressedLength).toBe(6);
8+
expect(chars.slice(0, compressedLength)).toEqual([
9+
"a",
10+
"2",
11+
"b",
12+
"2",
13+
"c",
14+
"3",
15+
]);
16+
});
17+
18+
it("should return the original string if it cannot be compressed", () => {
19+
const chars: string[] = ["a"];
20+
const compressedLength = compress(chars);
21+
expect(compressedLength).toBe(1);
22+
expect(chars.slice(0, compressedLength)).toEqual(["a"]);
23+
});
24+
25+
it("should handle multiple repeating characters", () => {
26+
const chars: string[] = [
27+
"a",
28+
"b",
29+
"b",
30+
"b",
31+
"b",
32+
"b",
33+
"b",
34+
"b",
35+
"b",
36+
"b",
37+
"b",
38+
"b",
39+
"b",
40+
];
41+
const compressedLength = compress(chars);
42+
expect(compressedLength).toBe(4);
43+
expect(chars.slice(0, compressedLength)).toEqual(["a", "b", "1", "2"]);
44+
});
45+
46+
it("should handle alternating characters", () => {
47+
const chars: string[] = ["a", "a", "a", "b", "b", "a", "a"];
48+
const compressedLength = compress(chars);
49+
expect(compressedLength).toBe(6);
50+
expect(chars.slice(0, compressedLength)).toEqual([
51+
"a",
52+
"3",
53+
"b",
54+
"2",
55+
"a",
56+
"2",
57+
]);
58+
});
59+
60+
it("should handle an empty string", () => {
61+
const chars: string[] = [];
62+
const compressedLength = compress(chars);
63+
expect(compressedLength).toBe(0);
64+
expect(chars.slice(0, compressedLength)).toEqual([]);
65+
});
66+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export function compress(chars: string[]): number {
2+
let writeIndex = 0; // Index to write compressed characters
3+
let readIndex = 0; // Index to read source characters
4+
5+
while (readIndex < chars.length) {
6+
const currentChar = chars[readIndex];
7+
let count = 0;
8+
9+
// Counting the number of repeated characters
10+
while (readIndex < chars.length && chars[readIndex] === currentChar) {
11+
readIndex++;
12+
count++;
13+
}
14+
15+
// Write a compressed character
16+
chars[writeIndex] = currentChar;
17+
writeIndex++;
18+
19+
// If the character is repeated more than once, record the number of repetitions
20+
if (count > 1) {
21+
for (const digit of count.toString().split("")) {
22+
chars[writeIndex] = digit;
23+
writeIndex++;
24+
}
25+
}
26+
}
27+
28+
// Returning the new length of the compressed string
29+
return writeIndex;
30+
}

0 commit comments

Comments
 (0)