Я подумав про підхід, який може спрацювати.
По-перше, при попередній обробці потрібно вставити всі списки менше ніж половину введеного розміру ( n / 3) до списку.
Подано рядок: 0000010101000100
(зауважте, що цей конкретний приклад дійсний)
Вставте в список всі прости (1) від 1 до (16/2): {1, 2, 3, 4, 5, 6, 7}
Потім розділіть його навпіл:
100000101 01000100
Продовжуйте робити це, поки не доберетеся до рядків розміром 1. Для всіх рядків розміру-один із значком 1 додайте індекс рядка до списку можливостей; в іншому випадку поверніть -1 за провал.
Вам також потрібно буде повернути список ще можливих відстаней, пов'язаних з кожним стартовим індексом. (Почніть зі списку, який ви склали вище, і видаліть номери під час переходу) Тут порожній список означає, що ви маєте справу лише з одним 1, і тому будь-який інтервал можливий у цей момент; інакше список включає проміжки, які необхідно виключити.
Отже, продовжуючи приклад вище:
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
На першому кроці комбайна зараз у нас вісім комплектів з двох. По-перше, у нас є можливість множини, але ми дізнаємось, що проміжок через 1 неможливий через те, що там знаходиться інший нуль. Тож повертаємо 0 (для індексу) і {2,3,4,5,7} за те, що проміжок через 1 неможливий. По-друге, у нас нічого немає і тому повертаємо -1. У третьому ми маємо матч без проміжків, усунутих в індексі 5, тому повертаємо 5, {1,2,3,4,5,7}. У четвертій парі повертаємо 7, {1,2,3,4,5,7}. По-п'яте, поверніть 9, {1,2,3,4,5,7}. У шостому поверніть -1. У сьомому повернути 13, {1,2,3,4,5,7}. У восьмій поверніться -1.
Поєднавши знову чотири набори з чотирьох, ми маємо:
1000
: Повернення (0, {4,5,6,7})
0101
: Повернення (5, {2,3,4,5,6,7}), (7, {1,2,3,4,5,6 , 7})
0100
: Повернення (9, {3,4,5,6,7})
0100
: Повернення (13, {3,4,5,6,7})
Об'єднання у вісім:
10000101
: Повернення (0, {5,7}), (5, {2,3,4,5,6,7}), (7, {1,2,3,4,5,6,7})
01000100
: Повернення (9, {4,7}), (13, {3,4,5,6,7})
Об’єднання в набір з шістнадцяти:
10000101 01000100
По мірі просування ми продовжуємо перевіряти всі можливості досі. До цього кроку ми залишили речі, які вийшли за межі кінця рядка, але тепер ми можемо перевірити всі можливості.
В основному ми перевіряємо перший 1 з проміжками 5 і 7 і виявляємо, що вони не відповідають рівню 1. (Зверніть увагу, що кожна перевірка КОНСТАНТНА, а не лінійний час) Потім ми перевіряємо другий (індекс 5) з проміжками 2, 3, 4, 5, 6 і 7 - або ми б, але ми можемо зупинитися на 2, оскільки що насправді відповідає.
Фу! Це досить довгий алгоритм.
Я не знаю на 100%, чи це O (n log n) через останній крок, але все, що там, безумовно, є O (n log n) , наскільки я можу сказати. Я повернусь до цього пізніше і спробую вдосконалити останній крок.
EDIT: Я змінив свою відповідь, щоб відобразити коментар Welbog. Вибачте за помилку. Я також напишу трохи псевдокоду пізніше, коли отримаю трохи більше часу, щоб розшифрувати те, що я написав ще раз. ;-)