在字串 A 中刪除所有出現在字串 B 中的字符,是經典的字串處理面試題。本文提供O(n + m) 時間、O(1) 空間的原地刪除算法,附完整代碼與關鍵技巧解析。
A (可修改)、字串 B (刪除字符集)A,移除所有 B 中出現的字符A = "hello world", B = "ewd" → A = "hllo orl"void deleteWord(char *dest, char *word) {
int len1 = strlen(dest);
int len2 = strlen(word);
// 1. 建立字符查找表 (ASCII 256)
int lookup[256] = {0};
for (int i = 0; i < len2; i++)
lookup[(unsigned char)word[i]] = 1; // 標記需刪除字符
// 2. 雙指針原地覆蓋
int write_idx = 0;
for (int read_idx = 0; read_idx < len1; read_idx++) {
if (!lookup[(unsigned char)dest[read_idx]]) {
dest[write_idx++] = dest[read_idx]; // 保留字符前移
}
}
dest[write_idx] = '\0'; // 新字串結束
}
| 技巧 | 作用 | ||
|---|---|---|---|
unsigned char 強制轉型 | 避免負索引 (char 有無號實現相關),安全訪問 lookup[0~255] | ||
查找表 lookup[256] | O(1) 判斷字符是否在刪除集,空間固定 256 int | ||
雙指針 read_idx/write_idx | 原地覆蓋,無需額外緩衝區,單次遍歷完成 | ||
最終補 '\0' | 正確終止新字串,避免殘留舊字符 |
| 算法 | 時間 | 空間 | 備註 |
|---|---|---|---|
| 後移法 (原文) | O(n²) | O(1) | 簡單但低效 |
| 雙指針 + 查找表 (本文) | O(n + m) | O(1) (256 int) | 最優解 |
| 新建字串 | O(n + m) | O(n) | 簡單但額外空間 |
掌握查找表 + 雙指針原地覆蓋模式,可解決「過濾/刪除/保留字符」大類問題,是字串處理的核心套路。