Kiểm tra tính hợp lệ của dấu ngoặc¶
Yêu cầu¶
Viết chương trình kiểm tra một chuỗi các dấu ngoặc có cân bằng hay không (hoặc hợp lệ hay không).
Biết rằng chuỗi này là sự kết hợp của các loại dấu ngoặc sau: () {} [].
Ví dụ:
({[()]})
→ Hợp lệ
({[([)])})
→ Không hợp lệ
Input¶
Dữ liệu đầu vào gồm nhiều dòng. Mỗi dòng là một chuỗi các ký tự dấu ngoặc.
Output¶
Dữ liệu đầu ra là hợp lệ hoặc không hợp lệ.
Bộ test¶
Input mẫu¶
Ouput mẫu¶
({[()]}) -> Hợp lệ
({[([)])}) -> Không hợp lệ
({[]}) -> Hợp lệ
((())){}[] -> Hợp lệ
((()) -> Không hợp lệ
Cách giải đề xuất¶
Ý tưởng¶
Ta sử dụng một ngăn xếp để lưu trữ từng dấu ngoặc mở {
[
(
hoặc dấu ngoặc đóng }
]
)
.
Khi gặp dấu ngoặc mở, ta đẩy vào ngăn xếp. Còn khi gặp dấu ngoặc đóng, ta so khớp với phần tử đỉnh của ngăn xếp xem chúng (dấu ngoặc đóng và phần tử đỉnh) có tạo thành một cặp ngoặc hợp lệ hay không.
Nếu hợp lệ, ta loại bỏ phần tử đỉnh khỏi ngăn xếp. Và cứ như thế, khi đã xét hết các ký tự trong chuỗi, thì kiểm tra ngăn xếp xem đã lấy hết các dấu ngoặc ra chưa. Nếu đã lấy ra hết, tức toàn bộ dấu ngoặc đã khớp nhau, thì nghĩa là chuỗi ban đầu hợp lệ.
(Phần diễn giải trên mang tính đại khái. Khi đi vào chi tiết, cần chú ý xét các trường hợp chưa đề cập đến.)
Đọc dữ liệu đầu vào¶
Khai báo biến data
chứa dữ liệu đầu vào.
Trong chương trình chính, ta đọc dữ liệu đầu vào thành danh sách các chuỗi, lưu trong biến lines
.
-
strip()
được thực hiện trước, dùng để cắt bỏ các khoảng trắng ở hai đầu củadata
.split('\n')
được thực hiện sau, dựa trên ký tự xuống dòng'\n'
để phân chia các dòng thành các phần tử của danh sáchlines
.
Các hàm cơ bản trên ngăn xếp¶
Trước hết, ta viết các hàm đã học dùng để thao tác với ngăn xếp.
Xử lý¶
Ta viết hàm is_balanced_parentheses
dùng để kiểm tra một chuỗi ngoặc là hợp lệ hay không.
Hàm này gồm một tham số là chuỗi s
cần kiểm tra và giá trị trả về là True
hoặc False
, tương ứng với hợp lệ hoặc không hợp lệ.
Bước 1: Khởi tạo ngăn xếp chứa các ngoặc và biến brackets
có kiểu dictionary
chứa các cặp ngoặc khớp nhau.
-
dictionary
là kiểu dữ liệu của Python, dùng để chứa các cặpkey: value
. Trong đó:key
là duy nhất, nghĩa là không có key nào trùng nhau, và được dùng để truy xuấtvalue
.value
có kiểu dữ liệu tuỳ ý.
Ví dụ: cặp thứ nhất có
key
là')'
vàvalue
là'('
.
Bước 2:
Dùng vòng lặp for duyệt các ký tự trong chuỗi s
:
- Trường hợp 1: Nếu ký tự đang xét là dấu ngoặc mở thì "đẩy" vào ngăn xếp.
- Trường hợp 2: Ngược lại, nếu ký tự đang xét là dấu ngoặc đóng thì:
- Trường hợp 2.1: Nếu ngăn xếp rỗng, nghĩa là ngăn xếp không có ngoặc mở để khớp với ký tự đang xét, dẫn đến chuỗi
s
không hợp lệ. - Trường hợp 2.2: Nếu không rỗng nhưng phần tử đỉnh của ngăn xếp không khớp với ký tự đang xét thì chuỗi
s
cũng không hợp lệ. - Trường hợp 2.3: Nếu phần tử đỉnh khớp với ký tự đang xét thì loại bỏ phần tử đỉnh này.
- Trường hợp 2.1: Nếu ngăn xếp rỗng, nghĩa là ngăn xếp không có ngoặc mở để khớp với ký tự đang xét, dẫn đến chuỗi
-
char
là ký tự đang xét.brackets[char]
là lấyvalue
củachar
, tức lấy "cột bên phải" của dictionarybrackets
, đồng nghĩa là một dấu ngoặc mở.Nếu dấu ngoặc mở này không giống phần tử đỉnh
peek(stack)
thì chuỗis
không hợp lệ.
Bước 3:
Sau khi kết thúc vòng lặp for, nghĩa là đã hết ký tự cần xét trong s
, thì ta kiểm tra ngăn xếp.
Nếu ngăn xếp không còn phần tử nào, tức toàn bộ ngoặc đã khớp, đã được lấy ra khỏi ngăn xếp trước đó, thì đồng nghĩa chuỗi s
hợp lệ.
Ngược lại, nếu ngăn xếp vẫn còn dấu ngoặc nào đó, tức "nó" không khớp với dấu ngoặc đóng nào cả, thì đồng nghĩa chuỗi s
không hợp lệ.
In dữ liệu đầu ra¶
Trong chương trình chính, ta gọi hàm is_balanced_parentheses()
để kiểm tra tính hợp lệ của từng chuỗi.
Mã nguồn¶
Chương trình Python hoàn chỉnh đặt tại Google Colab.