南陽理工 OJ 題目:給定只含 ()[] 的字串,判斷括號是否合法配對。限制:字串長度 < 10000,測試組數 < 5。標準解法用堆疊,但作者未學資料結構,另闢蹊徑。
利用字串可修改特性,採用雙指針回溯 + 字元標記策略:
No) 或 ]'0' 的字元')' - '(' = 1']' - '[' = 2No'0''0'(說明所有字元配對完畢)→ Yes
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void deal(char str[]) {
int len = strlen(str);
int i, j, flag;
// 快速失敗
if (len % 2 != 0 || str[0] == ')' || str[0] == ']') {
printf("No\n");
return;
}
for (i = 0; i < len; i++) {
if (str[i] == ')' || str[i] == ']') {
// 向左尋找未配對的左括號
for (j = i - 1; j >= 0; j--) {
if (str[j] == '0') continue; // 跳過已配對
int diff = str[i] - str[j];
if (diff != 1 && diff != 2) { // 類型不匹配
printf("No\n");
return;
}
// 配對成功,標記消除
str[i] = str[j] = '0';
break;
}
}
}
// 全部配對完成的標誌:最後一字元被標記
if (str[len - 1] == '0')
printf("Yes\n");
else
printf("No\n"); // 有殘留未配對左括號
}
int main() {
int n;
char str[10000];
scanf("%d", &n);
while (n--) {
scanf("%s", str);
deal(str);
}
return 0;
}
| 指標 | 表現 | 說明 |
|---|---|---|
| 時間複雜度 | O(n²) | 最壞情況每個右括號回溯整個字串 |
| 空間複雜度 | O(1) | 原地修改,無額外空間 |
| 適用場景 | 小規模、單類型括號 | 不支援 {}、多類型混雜擴展性差 |
優點:無需堆疊資料結構,思路直觀,代碼極短,適合受限環境(如嵌入式無標準庫)。
缺點:破壞原始字串、O(n²) 效率低、擴展性差(新增括號類型需修改差值判斷邏輯)、無法輸出錯誤位置。
堆疊天然契合「後進先出」的括號嵌套語義:
// 堆疊版核心邏輯 (O(n) 時間, O(n) 空間)
for (c : str) {
if (c == '(' || c == '[') push(c);
else if (c == ')' && top() == '(') pop();
else if (c == ']' && top() == '[') pop();
else return false;
}
return empty();
堆疊法可線性掃描、支援任意括號類型、易於擴展錯誤報告,是工業級解法。本文方法屬於「特定約束下的技巧性解法」,理解其局限性同樣重要。