Đủ số lượng chưa chắc đúng thứ tự
Với hai loại ngoặc `()` và `[]`, mỗi dấu đóng phải khớp với **dấu mở chưa ghép gần nhất**. Chuỗi `([)]` có đủ số lượng từng loại nhưng sai vì khi gặp `)`, dấu mở gần nhất lại là `[`.
Duyệt từ trái sang phải: gặp dấu mở thì push; gặp dấu đóng mà ngăn xếp rỗng thì sai; nếu không rỗng, pop và so với loại mở tương ứng. Sau khi duyệt hết, ngăn xếp phải rỗng. Các kí tự khác được bỏ qua; thuật toán chỉ kiểm tra ngoặc, không kết luận toàn bộ biểu thức toán học đúng cú pháp.
Dừng ngay khi gặp dấu không khớp
Dùng các hàm ngăn xếp đã học. Bảng pairs cho biết dấu mở cần có ứng với mỗi dấu đóng.
```python
def brackets_ok(text):
S = Stack()
pairs = {')': '(', ']': '['}
for ch in text:
if ch in '([':
push(S, ch)
elif ch in pairs:
if isEmptyStack(S):
return False
if pop(S) != pairs[ch]:
return False
return isEmptyStack(S)
```
`brackets_ok('[(a+b)*c]')` cho True; `brackets_ok('([)]')` cho False. Chuỗi rỗng hoặc không có ngoặc cho True vì không có dấu nào chưa ghép.
Muốn mở rộng sang `{}`, thêm cặp `'}': '{'` vào pairs và thêm `{` vào chuỗi dấu mở. Phải thay cả hai chỗ, không chỉ đếm tổng số dấu.
Theo dõi tại thời điểm dễ nhầm
|Kí tự của ([)]|Ngăn xếp sau bước|Nhận xét|
|---|---|---|
|(|[(]|Thêm dấu mở|
|[|[(, []|Thêm dấu mở|
|)|—|Lấy [ nhưng cần (; kết luận sai ngay|
Nếu cần đếm các cặp của một chuỗi đã xác nhận đúng, số cặp ngoặc tròn bằng `text.count('(')`, số cặp ngoặc vuông bằng `text.count('[')`. Với `[(a+b)*(c-d)]`, có 2 cặp tròn và 1 cặp vuông. Nếu kiểm tra sai thì không báo số dấu mở như số cặp đã ghép đúng.
Bài luyện
Vì sao ([)] bị kết luận sai khi gặp dấu )?
Tổng số dấu mở và đóng ở đây bằng nhau.
Đúng. Phải ghép với đỉnh ngăn xếp.
Hai loại có thể lồng đúng như [()].
Ghép dấu mở gần nhất chưa ghép, không tùy chọn dấu đầu.
Lời giải
Sau ( rồi [, ngăn xếp có [ ở đỉnh. Khi gặp ), thuật toán cần lấy được (. Nó lại lấy [, nên hai loại không khớp và kết luận sai.
Bài luyện
Chuỗi nào được brackets_ok trả về True?
Dấu đóng xuất hiện khi chưa có dấu mở.
Dấu [ và ( chưa được đóng đúng thứ tự.
Hai loại ngoặc bắt chéo.
Đúng. Các dấu lồng đúng và hết chuỗi ngăn xếp rỗng.
Lời giải
Trong [(a+b)*(c-d)], mỗi cặp tròn đóng trước khi đóng ngoặc vuông ngoài cùng. Mọi dấu đóng khớp đỉnh ngăn xếp, cuối cùng không còn dấu mở.
Bài luyện
Duyệt xong chuỗi (a+[b])+(c nhưng ngăn xếp còn một dấu (. Kết luận nào đúng?
Đúng. Kết thúc phải có ngăn xếp rỗng.
Không gặp sai giữa chừng chưa đủ; vẫn phải kiểm cuối.
Không được tự bỏ dấu ngoặc trong dữ liệu.
Đếm dấu mở không chứng minh có cặp đúng.
Lời giải
Phần (a+[b]) đã ghép hết, nhưng (c để lại dấu mở (. Vì không có dấu đóng tương ứng, điều kiện ngăn xếp rỗng cuối quá trình không thỏa mãn.
Đang học