Tôi nghĩ về một cách tiếp cận chia rẽ và có thể làm việc.
Đầu tiên, trong quá trình tiền xử lý, bạn cần chèn tất cả các số nhỏ hơn một nửa kích thước đầu vào ( n / 3) vào danh sách.
Đưa ra một chuỗi: 0000010101000100
(lưu ý rằng ví dụ cụ thể này là hợp lệ)
Chèn tất cả các số nguyên tố (và 1) từ 1 đến (16/2) vào danh sách: {1, 2, 3, 4, 5, 6, 7}
Sau đó chia nó làm đôi:
100000101 01000100
Tiếp tục làm điều này cho đến khi bạn nhận được các chuỗi có kích thước 1. Đối với tất cả các chuỗi có một kích thước có 1 trong đó, hãy thêm chỉ mục của chuỗi vào danh sách các khả năng; mặt khác, trả về -1 cho thất bại.
Bạn cũng cần trả về một danh sách các khoảng cách khoảng cách vẫn có thể, được liên kết với từng chỉ số bắt đầu. (Bắt đầu với danh sách bạn đã thực hiện ở trên và xóa các số khi bạn đi) Ở đây, một danh sách trống có nghĩa là bạn chỉ giao dịch với 1 và vì vậy bất kỳ khoảng cách nào đều có thể vào thời điểm này; mặt khác, danh sách bao gồm các khoảng cách phải được loại trừ.
Vì vậy, tiếp tục với ví dụ trên:
1000 0101 0100 0100
10 00 01 01 01 00 01 00
1 0 0 0 0 1 0 1 0 1 0 0 0 1 0 0
Trong bước kết hợp đầu tiên, chúng ta có tám bộ hai bây giờ. Đầu tiên, chúng ta có khả năng của một tập hợp, nhưng chúng ta học được rằng khoảng cách 1 là không thể vì không có số 0 nào ở đó. Vì vậy, chúng tôi trả về 0 (cho chỉ mục) và {2,3,4,5,7} vì thực tế là khoảng cách bằng 1 là không thể. Trong lần thứ hai, chúng ta không có gì và vì vậy trả về -1. Trong phần ba, chúng ta có một trận đấu không có khoảng cách nào bị loại bỏ trong chỉ số 5, vì vậy hãy trả về 5, {1,2,3,4,5,7}. Trong cặp thứ tư, chúng tôi trả về 7, {1,2,3,4,5,7}. Trong phần năm, trả về 9, {1,2,3,4,5,7}. Trong lần thứ sáu, trả về -1. Trong phần bảy, trả lại 13, {1,2,3,4,5,7}. Trong lần thứ tám, trả về -1.
Kết hợp lại thành bốn bộ bốn, chúng ta có:
1000
: Trả về (0, {4,5,6,7})
0101
: Trả về (5, {2,3,4,5,6,7}), (7, {1,2,3,4,5,6 , 7})
0100
: Trả lại (9, {3,4,5,6,7})
0100
: Trả lại (13, {3,4,5,6,7})
Kết hợp thành bộ tám:
10000101
: Trả về (0, {5,7}), (5, {2,3,4,5,6,7}), (7, {1,2,3,4,5,6,7})
01000100
: Trả lại (9, {4,7}), (13, {3,4,5,6,7})
Kết hợp thành một bộ mười sáu:
10000101 01000100
Khi chúng tôi tiến bộ, chúng tôi tiếp tục kiểm tra tất cả các khả năng cho đến nay. Cho đến bước này, chúng tôi đã để lại những thứ vượt quá cuối chuỗi, nhưng bây giờ chúng tôi có thể kiểm tra tất cả các khả năng.
Về cơ bản, chúng tôi kiểm tra 1 đầu tiên với các khoảng cách 5 và 7 và thấy rằng chúng không xếp hàng lên 1. (Lưu ý rằng mỗi kiểm tra là CONSTANT, không phải thời gian tuyến tính) Sau đó, chúng tôi kiểm tra lần thứ hai (chỉ số 5) với các khoảng cách 2, 3, 4, 5, 6 và 7-- hoặc chúng tôi có thể dừng lại ở 2 mà thực sự phù hợp lên.
Phù! Đó là một thuật toán khá dài.
Tôi không biết 100% nếu đó là O (n log n) vì bước cuối cùng, nhưng mọi thứ cho đến đó chắc chắn là O (n log n) theo như tôi có thể nói. Tôi sẽ quay lại vấn đề này sau và cố gắng tinh chỉnh bước cuối cùng.
EDIT: Thay đổi câu trả lời của tôi để phản ánh nhận xét của Welbog. Xin lỗi vì lỗi. Tôi cũng sẽ viết một số mã giả sau, khi tôi có thêm một chút thời gian để giải mã những gì tôi đã viết lại. ;-)