Vì chúng ta chỉ có thể bỏ qua tất cả các ký tự chữ và số, nên chúng ta sẽ giả sử chuỗi chỉ chứa dấu ngoặc đơn từ bây giờ. Như trong câu hỏi, chỉ có một loại dấu ngoặc đơn, "()".
Nếu chúng ta tiếp tục loại bỏ các dấu ngoặc đơn cân bằng cho đến khi không thể xóa các dấu ngoặc cân bằng hơn, tất cả các dấu ngoặc đơn còn lại phải trông giống như "))) (((((tất cả các dấu ngoặc đơn không cân bằng. Quan sát này cho thấy rằng chúng ta nên tìm thấy bước ngoặt đầu tiên , trước đó chúng ta chỉ có dấu ngoặc đơn đóng không cân bằng và sau đó chúng ta chỉ có dấu ngoặc đơn mở không cân bằng.
Đây là thuật toán. Tóm lại, nó tính toán bước ngoặt đầu tiên. Sau đó, nó xuất ra dấu ngoặc đơn đóng thêm, quét chuỗi từ đầu sang phải cho đến khi bước ngoặt. Đối xứng, nó xuất ra dấu ngoặc đơn mở thêm, quét từ đầu đến bên trái cho đến khi bước ngoặt.
Đặt str
chuỗi là một mảng các ký tự, có kích thước là .n
Khởi tạo turning_point=0, maximum_count=0, count=0
. Đối với mỗi i
từ 0
để n-1
làm như sau.
- Nếu
str[i] = ')'
, thêm 1 vào count
; mặt khác, trừ 1.
- Nếu
count > maximum_count
, đặt turning_point=i
và maximum_count=count
.
Bây giờ turning_point
là chỉ số của bước ngoặt.
Đặt lại maximum_count=0, count=0
. Đối với mỗi i
từ 0
để turning_point
làm như sau.
- Nếu
str[i] = ')'
, thêm 1 vào count
; mặt khác, trừ 1.
- Nếu
count > maximum_count
, đặt maximum_count = count
. Đầu ra i
là chỉ số của dấu ngoặc đơn đóng không cân bằng.
Đặt lại maximum_count=0, count=0
. Đối với mỗi i
từ n-1
để turning_point+1
xuống làm như sau.
- Nếu
str[j] = '('
, thêm 1 vào count
; mặt khác, trừ 1.
- Nếu
count > maximum_count
, đặt maximum_count = count
. Đầu ra i
là chỉ số của dấu ngoặc đơn mở không cân bằng.
Rõ ràng là thuật toán chạy trong thời gian và bộ nhớ phụ và bộ nhớ đầu ra , trong đó là số dấu ngoặc đơn không cân bằng.O(n)O(1)O(u)u
Nếu chúng ta phân tích thuật toán ở trên, chúng ta sẽ thấy rằng, trên thực tế, chúng ta không cần phải tìm và sử dụng bước ngoặt nào cả. Quan sát tốt đẹp rằng tất cả các dấu ngoặc đóng không cân bằng xảy ra trước khi tất cả các dấu ngoặc mở không cân bằng có thể bị bỏ qua mặc dù thú vị.
Chỉ cần nhấn "chạy" để xem một số kết quả thử nghiệm.
Bài tập 1. Chỉ ra rằng thuật toán trên sẽ xuất ra một tập các dấu ngoặc đơn với số lượng thẻ ít nhất sao cho các dấu ngoặc đơn còn lại được cân bằng.
Bài toán 1. Chúng ta có thể khái quát thuật toán cho trường hợp khi chuỗi chứa hai loại dấu ngoặc đơn như "() []" không? Chúng ta phải xác định cách nhận biết và xử lý tình huống mới, trường hợp xen kẽ, "([)]".