İşe yarayacak bir böl ve fethet yaklaşımı düşündüm.
İlk olarak, ön işlemede, giriş boyutunuzun yarısından ( n / 3) küçük tüm sayıları bir listeye eklemeniz gerekir .
Bir dize verildiğinde: 0000010101000100
(bu özel örneğin geçerli olduğunu unutmayın)
Tüm astarları (ve 1) 1'den (16/2) bir listeye ekleyin: {1, 2, 3, 4, 5, 6, 7}
Sonra ikiye bölün:
100000101 01000100
Boyut 1 dizelerine ulaşıncaya kadar bunu yapmaya devam edin. İçinde 1 olan tüm boyut bir dizeler için dizenin dizinini olasılıklar listesine ekleyin; aksi takdirde, hata için -1 döndürür.
Ayrıca, her bir başlangıç diziniyle ilişkili, hala mümkün olan boşluk mesafelerinin bir listesini döndürmeniz gerekir. (Yukarıda yaptığınız listeyle başlayın ve hareket halindeyken sayıları kaldırın) Burada boş bir liste yalnızca bir 1 ile uğraştığınız anlamına gelir ve bu nedenle bu noktada herhangi bir boşluk mümkün olabilir; aksi takdirde liste, dışlanması gereken boşluklar içerir.
Yukarıdaki örnekle devam edelim:
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
İlk birleştirme adımında, şimdi ikiden oluşan sekiz setimiz var. İlkinde, bir küme olasılığımız var, ancak diğer sıfırın orada olması nedeniyle 1 ile boşluk bırakmanın imkansız olduğunu öğreniyoruz. Bu nedenle 1 (aralık için) imkansız olduğu için 0 (dizin için) ve {2,3,4,5,7} değerlerini döndürüyoruz. İkincisinde, hiçbir şeyimiz yok ve -1'e geri dönüyoruz. Üçüncüsü, indeks 5'te boşluk bırakılmamış bir eşleşmemiz var, bu yüzden 5 dönüşü, {1,2,3,4,5,7}. Dördüncü çiftte 7, {1,2,3,4,5,7} döndürüyoruz. Beşinci bölümde, 9 dönüşü, {1,2,3,4,5,7}. Altıncı sırada -1 döndürün. Yedinci sırada 13 dönüş, {1,2,3,4,5,7}. Sekizinci'de -1 döndür.
Tekrar dörtlü dört set halinde birleştirdik:
1000
: Dönüş (0, {4,5,6,7})
0101
: Dönüş (5, {2,3,4,5,6,7}), (7, {1,2,3,4,5,6 , 7})
0100
: Geri Dönüş (9, {3,4,5,6,7})
0100
: Geri Dönüş (13, {3,4,5,6,7})
Sekiz set halinde birleştirmek:
10000101
: Dönüş (0, {5,7}), (5, {2,3,4,5,6,7}), (7, {1,2,3,4,5,6,7})
01000100
: Dönüş (9, {4,7}), (13, {3,4,5,6,7})
On altılık bir kümeye birleştiğinde:
10000101 01000100
İlerledikçe, şimdiye kadar tüm olasılıkları kontrol etmeye devam ediyoruz. Bu adıma kadar dizenin sonunu aşan şeyleri bıraktık, ancak şimdi tüm olasılıkları kontrol edebiliriz.
Temel olarak, ilk 1'i 5 ve 7 aralıklarla kontrol ediyor ve 1'lere kadar sıralanmadığını buluyoruz. (Her bir kontrolün lineer zaman değil SABİT olduğunu unutmayın) Sonra ikincisini (indeks 5) 2, 3, 4, 5, 6 ve 7 aralıklarıyla kontrol ederiz, yoksa yaparız, ancak 2'de durabiliriz aslında eşleşir.
Uf! Bu oldukça uzun bir algoritma.
Son adımdan dolayı O (n log n) olup olmadığını% 100 bilmiyorum , ancak oraya kadar her şey kesinlikle söyleyebildiğim kadarıyla O (n log n) . Buna daha sonra geri döneceğim ve son adımı düzeltmeye çalışacağım.
EDIT: Cevabımı Welbog'un yorumunu yansıtacak şekilde değiştirdi. Hata için özür dileriz. Daha sonra tekrar yazdığımı deşifre etmek için biraz daha zaman bulduğumda da sahte kod yazacağım. ;-)