Catatan tentang metodologi
Saya berpikir sedikit tentang masalah ini, dan menemukan solusi. Ketika saya membaca jawaban Saeed Amiri , saya menyadari bahwa apa yang saya temukan adalah versi khusus dari algoritma pencarian hasil terpanjang standar untuk urutan panjang 3. Saya memposting cara saya datang dengan solusi, karena saya pikir itu adalah contoh menarik dari pemecahan masalah.
Versi dua elemen
Mari kita mulai dari yang kecil: alih-alih mencari tiga indeks di mana elemen-elemennya berurutan, mari kita cari dua: sedemikian rupa sehingga A [ i ] < A [ j ] .saya < jA [ i ] < A [ j ]
Jika menurun (yaitu ∀ i < j , A [ i ] ≥ A [ j ] , atau setara dengan ∀ i , A [ i ] ≥ A [ i + 1 ] ), maka tidak ada indeks seperti itu. Kalau tidak, ada indeks i sedemikian rupa sehingga A [ i ] < A [ i + 1 ] .SEBUAH∀ i < j , A [ i ] ≥ A [ j ]∀ i , A [ i ] ≥ A [ i + 1 ]sayaA [ i ] < A [ i + 1 ]
Kasus ini sangat sederhana; kami akan mencoba menyamaratakannya. Ini menunjukkan bahwa masalah seperti yang disebutkan tidak dapat dipecahkan: indeks yang diminta tidak selalu ada. Jadi kami lebih suka bertanya apakah algoritma mengembalikan indeks yang valid, jika ada, atau mengklaim dengan benar bahwa tidak ada indeks seperti itu.
Datang dengan algoritme
Saya akan menggunakan istilah berikutnya untuk berarti ekstrak dari array terdiri dari indeks yang mungkin tidak berurutan ( ( A [ i 1 ] , … , A [ i m ] ) dengan i 1 < ⋯ < i m ), dan jalankan berarti elemen berurutan dari A ( ( A [ i ] , A [ i + 1 ] , ... , A [SEBUAH( A [ i1] , … , A [ im] )saya1< ⋯ < imSEBUAH ).( A [ i ] , A [ i + 1 ] , ... , A [ i + m - 1 ] )
Kami hanya melihat bahwa indeks yang diminta tidak selalu ada. Strategi kami adalah belajar ketika indeks tidak ada. Kami akan melakukan ini dengan mengandaikan kami berusaha menemukan indeks dan melihat bagaimana kesalahan pencarian kami. Maka kasus-kasus di mana pencarian tidak salah akan menyediakan algoritma untuk menemukan indeks.
Dengan dua indeks, kita bisa menemukan indeks berurutan. Dengan tiga indeks, kita mungkin tidak dapat menemukan dan k = j + 1 . Namun, kita dapat mempertimbangkan kasus ketika ada serangkaian tiga elemen yang benar-benar meningkat ( A [ i ] < A [ i + 1 ] < A [ i + 2 ] ) yang harus dipecahkan, karena mudah untuk mengenali proses tersebut, dan lihat bagaimana kondisi ini mungkin tidak terpenuhi. Misalkan urutan tidak memiliki peningkatan panjang menjalankan 3.j = i + 1k = j + 1A [ i ] < A [ i + 1 ] < A [ i + 2 ]
Urutan hanya memiliki peningkatan ketat menjalankan panjang 2 (yang saya akan memanggil pasangan yang diperintahkan pendek), dipisahkan oleh penurunan jangka panjang setidaknya 2. Dalam rangka untuk menjalankan peningkatan ketat untuk menjadi bagian dari urutan 3 elemen yang meningkat, harus ada elemen sebelumnya i sehingga A [ i ] < A [ j ] atau elemen selanjutnya k sedemikian sehingga A [ j + 1 ] < A [ kA [ j ] < A [ j + 1 ]sayaA [ i ] < A [ j ]k .A [ j + 1 ] < A [ k ]
Suatu kasus ketika atau k tidak ada adalah ketika setiap pasangan yang dipesan seluruhnya lebih rendah dari yang berikutnya. Ini belum semuanya: ketika pasangan saling terkait, kita perlu membandingkannya dengan lebih halus.sayak
Paling kiri elemen dari subsequence meningkat perlu datang lebih awal dan menjadi kecil. Elemen j berikutnya harus lebih besar, tetapi sekecil mungkin untuk dapat menemukan elemen ketiga yang lebih besar k . Elemen pertama i tidak selalu elemen terkecil dalam urutan, dan itu tidak selalu yang pertama ada elemen berikutnya yang lebih besar, baik - kadang-kadang ada lebih rendah 2 elemen berikutnya, dan kadang-kadang ada yang lebih baik cocok untuk minimum yang sudah ditemukan.sayajksaya
saya( i , j )ksaya( i , j )( i , j )saya′> jA [ i′] < A [ i ]saya′saya( i , j )j′A [ j′] < A [ j ]( saya′, j′)
Pernyataan algoritma
Diberikan dalam sintaksis Python, tetapi berhati-hatilah karena saya belum mengujinya.
def subsequence3(A):
"""Return the indices of a subsequence of length 3, or None if there is none."""
index1 = None; value1 = None
index2 = None; value2 = None
for i in range(0,len(A)):
if index1 == None or A[i] < value1:
index1 = i; value1 = A[i]
else if A[i] == value1: pass
else if index2 == None:
index2 = (index1, i); value2 = (value1, A[i])
else if A[i] < value2[1]:
index2[1] = i; value2[1] = A[i]
else if A[i] > value2[1]:
return (index2[0], index2[1], i)
return None
Sketsa bukti
index1
adalah indeks minimum bagian array yang telah dilalui (jika terjadi beberapa kali, kami mempertahankan kejadian pertama), atau None
sebelum memproses elemen pertama. index2
menyimpan indeks peningkatan urutan panjang 2 di bagian array yang sudah dilintasi yang memiliki elemen terbesar terendah, atau None
jika urutan seperti itu tidak ada.
Ketika return (index2[0], index2[1], i)
berjalan, kami memiliki value2[0] < value[1]
(ini adalah invarian dari value2
) dan value[1] < A[i]
(jelas dari konteksnya). Jika loop berakhir tanpa menerapkan pengembalian awal, baik value1 == None
, dalam hal ini tidak ada penambahan panjang 2 panjang apalagi 3, atau value1
berisi peningkatan panjang 2 panjang yang memiliki elemen terbesar terendah. Dalam kasus terakhir, kami selanjutnya memiliki invarian bahwa tidak ada peningkatan setelah panjang 3 berakhir lebih awal dari value1
; Oleh karena itu elemen terakhir dari setiap urutan tersebut, ditambahkan ke value2
, akan membentuk urutan berikutnya yang meningkat dari panjang 3: karena kami juga memiliki invarian yang value2
bukan bagian dari peningkatan berikutnya dari panjang 3 yang terkandung dalam bagian array yang sudah dilalui, ada tidak ada urutan seperti itu di seluruh array.
Membuktikan invarian yang disebutkan di atas dibiarkan sebagai latihan untuk pembaca.
Kompleksitas
O ( 1 )HAI( 1 )O (n )
Bukti formal
Ditinggalkan sebagai latihan untuk pembaca.