Ba ngăn xếp có thể được thực hiện trong một mảng, với thời gian đẩy / bật O (1) không?


9

Hai ngăn xếp có thể được thực hiện một cách hiệu quả bằng cách sử dụng một mảng có kích thước cố định: ngăn xếp số 1 bắt đầu từ đầu bên trái và phát triển sang bên phải và ngăn xếp số 2 bắt đầu từ đầu bên phải và phát triển sang bên trái. Là giống nhau có thể cho ba ngăn xếp?

Cụ thể hơn, có thể thực hiện ba ngăn xếp với các điều kiện sau:

  1. Bạn có một mảng kích thước cố định có thể chứa N đối tượng.
  2. Miễn là tổng của ba kích thước ngăn xếp là <N, không nên thất bại.
  3. Cả hai hoạt động đẩy () và pop () sẽ mất thời gian O (1).
  4. Ngoài mảng, bạn chỉ có thể sử dụng không gian bổ sung O (1).

Dưới đây là ví dụ về các giải pháp không thỏa mãn các yêu cầu này:

  • Chia mảng thành 3 phần cố định và sử dụng từng phần cho một ngăn xếp (vi phạm 2).
  • Tương tự như trên nhưng với ranh giới di chuyển giữa các ngăn xếp (vi phạm 3).
  • Thực hiện dựa trên danh sách liên kết đơn giản (vi phạm 4).

Tôi sẽ chấp nhận các thuật toán không tầm thường hoặc bằng chứng bất khả thi ngay cả khi chúng không đáp ứng tất cả các điều kiện (1) - (4), ví dụ, thuật toán trong đó đẩy / pop mất thời gian khấu hao O (1) hoặc trong đó bộ nhớ bổ sung nhỏ hơn O (N), ví dụ O (log N). Hoặc một bằng chứng không thể chứng minh cho thấy, ví dụ, việc truy cập ít hơn 5 phần tử của mảng trên mỗi lần đẩy / pop là không thể.


1
Tôi không biết nếu bạn coi đây là vi phạm yêu cầu 4, nhưng nếu mỗi "đối tượng" trong mảng đối tượng N của bạn có thể bao gồm một trường bổ sung như chỉ mục số nguyên, thì bạn có thể triển khai "danh sách được liên kết" bên trong mảng của mình . Bạn có thể giữ chỉ mục trên cùng của mỗi trong số 3 ngăn xếp bằng cách sử dụng 3 biến ngoài và mỗi "đối tượng" có thể trỏ đến phần tử trước đó là ngăn xếp của nó.
Avi Tal

Theo "đối tượng", ý tôi là những thứ mà Push () chấp nhận và pop () trả về. Từ quan điểm thực hiện ngăn xếp, chúng chỉ là những đốm dữ liệu mờ đục (ví dụ, một đối tượng có thể là số nguyên 32 bit). Việc thực hiện ngăn xếp không nên sửa đổi các đối tượng này theo bất kỳ cách nào.
dùng1020406

1
N

O(N)

O(N)

Câu trả lời:


6

Θ(nε)Θ(n) nn


0

Gọi N là độ dài của mảng bên dưới. Tôi có thể tưởng tượng các ngăn xếp như các danh sách liên kết của các khối lớn, do đó tổng số khối không nhiều hơn O (log2 (N)). Đặt ngăn xếp thứ ba giữa hai cái đầu tiên, tại chỉ số N / 2. Vì vậy, chúng tôi có 3 khu vực chiếm đóng và 2 khu vực miễn phí. Khi một ngăn xếp không thể chấp nhận phần tử tiếp theo, điều này có nghĩa là một vùng trống đã hết. Nếu người kia cũng kiệt sức thì toàn bộ ký ức đã cạn kiệt. Mặt khác, có một khu vực miễn phí khác với kích thước không quá N / 2. Tiếp tục ngăn xếp tràn vào khu vực miễn phí đó. sao cho toàn bộ cấu hình giống với bố cục ban đầu của ngăn xếp. Vì bộ nhớ trống bây giờ không quá một nửa so với ban đầu, nên sẽ không có nhiều hơn log2 (N) của các hoạt động liên kết như vậy. Mỗi hoạt động liên kết yêu cầu số lượng bộ nhớ cố định để lưu trạng thái trước đó của ngăn xếp. Vì thế,


1
Làm thế nào để bạn tái chế bộ nhớ thu được bằng cách bật các thứ từ một trong những khối lớn?
Emil Jeřábek

Câu hỏi hay. Câu trả lời nhanh là đoạn mà trở thành miễn phí trả lại bộ nhớ của nó cho khu vực miễn phí nơi nó được lấy trước đó. Nhưng điều gì sẽ xảy ra nếu vùng trống bị thu hẹp kể từ thời điểm phân bổ bộ nhớ cho đoạn đó và đoạn này không liền kề với nó? Điều này dẫn đến sự phân mảnh bộ nhớ trống, có thể có hơn 2 khu vực miễn phí, làm hỏng tất cả công trình của tôi.
Alexei Kaigorodov

Popping thực sự là vấn đề ở đây, nhưng việc xây dựng của Alexei cung cấp giới hạn trên tốt đẹp cho phiên bản của vấn đề mà Dmitri đã hỏi trong các nhận xét: điều gì sẽ xảy ra nếu chúng ta yêu cầu tất cả các cú hích xảy ra trước tất cả các lần xuất hiện? Tôi tự hỏi liệu có bất cứ điều gì tốt hơn O (log N) là có thể trong trường hợp này.
dùng1020406
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.