Đảo ngược danh sách bằng hai hàng đợi


12

Câu hỏi này được lấy cảm hứng từ một câu hỏi hiện có về việc một ngăn xếp có thể được mô phỏng bằng cách sử dụng hai hàng đợi trong thời gian được khấu hao cho mỗi hoạt động của ngăn xếp hay không. Câu trả lời dường như chưa được biết. Dưới đây là một câu hỏi cụ thể hơn, tương ứng với trường hợp đặc biệt trong đó tất cả các hoạt động PUSH được thực hiện trước, tiếp theo là tất cả các hoạt động POP. Làm thế nào hiệu quả một danh sách các yếu tố N có thể được đảo ngược bằng cách sử dụng hai hàng đợi trống ban đầu? Các hoạt động pháp lý là:Ôi(1)N

  1. Enqueue phần tử tiếp theo từ danh sách đầu vào (đến đuôi của một trong hai hàng đợi).
  2. Dequeue phần tử ở đầu của một trong hai hàng đợi và liệt kê lại nó (đến đuôi của một trong hai hàng đợi).
  3. Dequeue phần tử ở đầu hàng đợi và thêm nó vào danh sách đầu ra.

Nếu danh sách đầu vào bao gồm các yếu tố , làm thế nào để số lượng hoạt động tối thiểu cần thiết để tạo danh sách đầu ra đảo ngược [ N , N - 1 , . . . , 2 , 1 ] cư xử thế nào? Một bằng chứng cho thấy nó phát triển nhanh hơn O ( N ) sẽ đặc biệt thú vị, vì nó sẽ giải quyết câu hỏi ban đầu theo cách tiêu cực.[1,2,...,N-1,N][N,N-1,...,2,1]Ôi(N)


Cập nhật (15 tháng 1 năm 2011): Vấn đề có thể được giải quyết trong , như thể hiện trong các câu trả lời đã gửi và nhận xét của họ; và giới hạn dưới của Ω ( N ) là tầm thường. Một trong những giới hạn này có thể được cải thiện?Ôi(Nđăng nhậpN)Ω(N)


Để làm rõ: bởi "phần tử cuối cùng từ một trong hai hàng" bạn đang đề cập đến phần tử ở đầu hàng đợi?
Peter Taylor

@Peter: Vâng, cảm ơn đã làm rõ. Tôi đã chỉnh sửa câu hỏi.
mjqxxxx

Có cả ngăn xếp danh sách đầu vào và đầu ra? Nếu vậy, n op1s (đến cùng hàng đợi) theo sau là n op3s thì ngược lại, phải không? Tôi nghĩ rằng tôi phải thiếu một cái gì đó quan trọng.
jbapple

@jbapple: Không, chúng không phải là ngăn xếp. Bạn cần ghi các phần tử vào danh sách đầu ra theo thứ tự ngược lại chúng được đọc từ danh sách đầu vào.
mjqxxxx

Câu trả lời:


11

Nếu N là sức mạnh của hai, tôi tin rằng các hoạt động O (N log N) là đủ, ngay cả đối với một vấn đề hạn chế hơn một chút trong đó tất cả các mục bắt đầu trên một trong các hàng đợi và phải kết thúc theo thứ tự ngược lại trên một trong các hàng đợi (không có danh sách đầu vào và đầu ra).

Trong các bước O (N), có thể bắt đầu với tất cả các thành phần trên một hàng đợi, phát "một cho bạn một cho tôi" để chia chúng thành các tập hợp con xen kẽ trên hàng đợi khác, sau đó ghép tất cả chúng lại thành một hàng đợi. Về mặt biểu diễn nhị phân của các vị trí của các mục, điều này thực hiện một thao tác xoay.

Trong các bước O (N) cũng có thể loại bỏ các cặp phần tử từ một hàng đợi, hoán đổi chúng, sau đó đặt chúng trở lại, đảo ngược tất cả các cặp. Về mặt biểu diễn nhị phân của các vị trí của các mục, điều này bổ sung cho bit thứ tự thấp của vị trí.

Bằng cách lặp lại O (log N) lần một lần xáo trộn và hoán đổi theo cặp, chúng ta có thể bổ sung cho tất cả các bit của biểu diễn nhị phân của các vị trí - điều tương tự như đảo ngược danh sách.


Sau đó, bạn có thể chia danh sách thành biểu diễn nhị phân và đảo ngược từng mảnh cho thuật toán O (n lg n), tôi nghĩ vậy.
jbapple

Tôi đã nghĩ người ta có thể mở rộng ra tất cả N bằng cách sử dụng cây 2-3 thay vì nhị phân, nhưng có lẽ ý tưởng của bạn đơn giản hơn. Nhưng làm thế nào để bạn đảo ngược từng phần O (log n) trong tổng số bước O (n log n)?
David Eppstein

Thời gian là O (tổng (2 ^ i) lg (2 ^ i)) cho i từ 0 đến [lg n], mà Wolfram alpha nói là O (n lg n): wolframalpha.com/input/?i=sum+ (2 ^ k) + log2 + (2 ^ k) + từ + 0 + đến + log2 + n
jbapple

Chắc chắn, nếu bạn có thể đảo ngược từng mảnh theo thời gian tỷ lệ với chiều dài của nó nhân với nhật ký của nó, bạn đã hoàn thành. Nhưng bạn phải đặt các mảnh ở đâu đó sau khi bạn đảo ngược chúng và điều đó có thể khiến việc đảo ngược các mảnh còn lại trở nên khó khăn hơn.
David Eppstein

Vấn đề đặt ra một "danh sách đầu ra". Chúng ta có thể đặt chúng ở đó không?
jbapple

1

ΣTôi= =0N/2-1(N-2Tôi-2)

Đặt tên cho hai hàng đợi có sẵn là trái và phải. Đây là ý tưởng cơ bản của thuật toán này với giả định rằng N là chẵn:

  1. Đọc các giá trị từ danh sách các phần tử ban đầu và đẩy tất cả các số lẻ vào hàng đợi bên trái và các số chẵn vào hàng đợi bên phải
  2. Một bước đầu tiên cách nhanh nhất để xuất giá trị tối đa là chuyển các phần tử N / 2-1 từ hàng đợi bên phải sang bên trái và đưa giá trị hàng đầu từ hàng đợi bên phải vào danh sách đầu ra
  3. Bây giờ chúng ta phải làm tương tự cho một hàng đợi khác - chuyển các phần tử N / 2-1 từ hàng đợi bên trái sang hàng bên phải và đưa phần tử trên cùng từ hàng đợi bên trái vào danh sách đầu ra
  4. Hoán đổi hàng đợi và lặp lại bước 2 và 3 cho N = N-2

Thật dễ dàng để xem thuật toán nên hoạt động như thế nào đối với N lẻ.


Bạn có thể sử dụng $ ... $ để chèn mã LaTeX-ish (trừ \).
Đánh dấu Reitblatt
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.