[LeetCode 解題紀錄] 443. String Compression
443. String Compression
https://leetcode.com/problems/string-compression/
Problem:
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 tos
. - 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.
You must write an algorithm that uses only constant extra space.
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 "bbbbbbbbbbbb". This compresses to "ab12".
Constraints:
1 <= chars.length <= 2000
chars[i]
is a lowercase English letter, uppercase English letter, digit, or symbol.
題意
建立一個方法,實作特定的演算法來壓縮一個字元陣列 chars
,字元陣列中會是連續的數個不同字元,例如:[“a”,”a”,”b”,”b”,”c”,”c”,”c”]
演算法如下:
- 如果某一個字元只出現一次,則不需要加入長度
- 如果某一個字元出現不只一次,則需要再下一個位置加上出現次數,ex: [“a”,”a”] -> [“a”, “2”]
- 如果超過 10 ,會被拆分成多個字符存儲在
chars
中。ex: [“a”, “1”, “2”] - 壓縮後的字串
s
不需要單獨返回,而是存儲在輸入的陣列chars
中。 - 修改輸入後,返回新陣列的長度。
問題解析:
這題有幾個重點要注意,一個是題目要求要直接修改本來的陣列,但是最後只需要回傳修改完後的長度,意思就是其實只關注前面被壓縮的結果,後面本來的字元不需要特別去從陣列裡面刪除。另一個要注意的就是回傳的數字必須是字串的形式,超過位數必須拆開表示。
解法
Two Pointers
回想剛剛有幾個重點,直接修改本來的陣列、只需要回傳修改完後的長度,想法會是在每一個字元的時候,都會先檢查這個字元往後會出現幾次,然後對下一個位置做數量的插入,因此我們需要兩個指針來記錄「目前讀取的位置」與「要寫入的位置」。
Sliding Window / Two Pointers 概念複習:
- 使用兩個指針:
writeIndex
用於指向應該寫入字元的位置,readIndex
用於讀取字元。 - 遍歷
chars
數組,對每個字元進行計數,計數完畢後將字元和計數結果寫入chars
。 - 最後返回新數組的長度
writeIndex
。
var compress = function(chars) {
let writeIndex = 0;
let readIndex = 0;
while (readIndex < chars.length) {
let char = chars[readIndex];
let count = 0;
// 計數連續重複的字元
while (readIndex < chars.length && chars[readIndex] === char) {
readIndex++;
count++;
}
// 寫入字元
chars[writeIndex] = char;
writeIndex++;
// 如果字元數大於1,寫入數字(必須轉成字串形式)
if (count > 1) {
// 處理進位問題
for (let digit of String(count)) {
chars[writeIndex] = digit;
writeIndex++;
}
}
}
// 返回新數組的長度
return writeIndex;
};
- 時間複雜度:O(N)
- 空間複雜度:O(1)