3612. Process String with Special Operations I
題目 / Problem
中文:給你一個字串 s,由小寫英文字母以及三個特殊字元 *、#、% 組成。從左到右依序處理 s,逐步建立一個新字串 result:
- 遇到小寫字母:把它接到
result的尾端。 - 遇到
*:刪除result的最後一個字元(如果result非空)。 - 遇到
#:把目前的result複製一份接在自己後面(長度變兩倍)。 - 遇到
%:把目前的result反轉。
處理完所有字元後,回傳最終的 result。
English: You are given a string s made of lowercase letters and the special characters *, #, %. Process s left to right, building a string result:
- A lowercase letter is appended to
result. *removes the last character ofresult(if any).#duplicatesresult(appends a copy of itself).%reversesresult.
Return the final result.
Constraints / 限制:
- 1 <= s.length <= 20
- s 只包含小寫字母與 *、#、%。
Example / 範例:
Input: s = "a#b%*"
Output: "ba"
a -> "a" (append 'a')
# -> "aa" (duplicate)
b -> "aab" (append 'b')
% -> "baa" (reverse)
* -> "ba" (remove last char)
名詞解釋 / Glossary
- 模擬 / Simulation:照著題目描述的規則,一步一步真的去執行每個操作,而不是尋找數學公式。當操作次數不大時,這是最直接也最不易出錯的做法。 Just follow the rules literally, step by step, instead of looking for a clever formula. Best when the input is small.
- 動態陣列 / Dynamic array:一個可以隨需要自動增長的陣列。在 C 裡我們用
malloc/realloc手動管理;在 C++ 裡std::string就是一個會自動長大的字元陣列。 An array that grows as needed;std::stringin C++ is exactly this for characters. - 長度欄位 / Length field(
len):我們用一個整數變數記錄result目前實際有幾個字元。append 就len++,刪除就len--,不必每次重算。 An integer tracking how many charactersresultcurrently holds, so append/delete are justlen++/len--. - 就地反轉 / In-place reverse:用兩個索引,一個從頭、一個從尾,互換字元並往中間靠攏,不需要額外開一個新陣列。 Swap characters from both ends moving inward — no extra array needed.
malloc/free:malloc(n)向系統要n位元組的記憶體並回傳一個指標;用完要free釋放。LeetCode 的 C 題要求你回傳一塊malloc出來的記憶體。malloc(n)requestsnbytes and returns a pointer; LeetCode expects you to return malloc'd memory.
思路
這題的關鍵觀察是:字串長度最多只有 20,而且每個 # 最多讓字串長度加倍。20 個字元裡就算全是 #,長度也不會超過 2^20(大約一百萬),完全在電腦能輕鬆處理的範圍內。所以我們不需要任何聰明的數學技巧,直接「照著題目說的做」就好——這就是模擬(simulation)。我們維護一個可變的字元緩衝區 result 和一個長度 len。從左到右掃過 s:是字母就寫到 result[len] 並把 len 加一;是 * 就在 len > 0 時把 len 減一(不必真的清除那個位元組,下次 append 會蓋過去);是 # 就把前 len 個字元再複製一份接到後面,長度變兩倍;是 % 就用頭尾雙索引就地反轉前 len 個字元。唯一要小心的是緩衝區要夠大:由於 # 會加倍,我們一開始就配置足夠大的空間(2^20 + 1)以容納最壞情況,避免越界。
The key observation is that the input length is at most 20, and each # at most doubles the string. Even 20 consecutive # operations cap the length at about 2^20 (~1 million), which is trivial for a computer. So no clever math is needed — we just do exactly what the problem says, a pure simulation. We keep a growable character buffer result plus a counter len. Scanning s left to right: a letter is written at result[len] and we increment len; a * decrements len only when len > 0 (we don't bother erasing the byte — a future append overwrites it); a # copies the current len characters onto the end, doubling the length; a % reverses the first len characters in place using two indices walking from the ends toward the middle. The one thing to be careful about is buffer size: because # doubles, we pre-allocate enough room (2^20 + 1) for the worst case so we never write out of bounds.
逐步走查 / Walkthrough
Input: s = "a#b%*". We track result (only the first len chars matter) and len.
| Step | char | Operation 操作 | result | len |
|---|---|---|---|---|
| start | — | 初始空字串 / empty | "" |
0 |
| 0 | a |
append a / 接上 a |
a |
1 |
| 1 | # |
duplicate / 複製:把 a 再接一份 |
aa |
2 |
| 2 | b |
append b / 接上 b |
aab |
3 |
| 3 | % |
reverse / 反轉前 3 個字元 | baa |
3 |
| 4 | * |
remove last / len--,最後的 a 被丟掉 |
ba |
2 |
最後用 result[len] = '\0' 收尾,得到 "ba"。
Finally terminate with result[len] = '\0', giving "ba".
Solution — C
// 演算法:純模擬。維護一個夠大的字元緩衝區 result 與長度 len,
// 逐字處理 s:字母 append、'*' 刪尾、'#' 複製加倍、'%' 就地反轉。
// Algorithm: pure simulation. Keep a large enough buffer `result` and a length
// `len`; for each char: letter -> append, '*' -> pop, '#' -> double, '%' -> reverse.
#include <stdlib.h> // malloc / free
#include <string.h> // strlen, memcpy
char* processStr(char* s) {
int n = strlen(s); // n = s 的長度 / length of input s
// '#' 最多把長度加倍;20 個字元最壞情況下長度可達 2^20。
// '#' doubles length; with up to 20 chars the worst case is 2^20.
// 多 +1 是為了結尾的 '