Saya ingin membuktikan atau menyangkal keberadaan suatu algoritma yang, mengingat array dari bilangan bulat, menemukan tiga indeks dan sedemikian rupa sehingga dan (atau menemukan bahwa tidak ada triple seperti itu) dalam waktu linier.
Ini bukan pertanyaan pekerjaan rumah; Saya melihatnya di forum pemrograman yang dibingkai sebagai "cobalah untuk mengimplementasikan algoritma seperti itu." Saya curiga tidak mungkin setelah berbagai percobaan. Intuisi saya mengatakan demikian, tetapi itu tidak berarti apa-apa.
Saya ingin membuktikannya secara formal. Bagaimana Anda melakukannya? Saya idealnya ingin melihat bukti yang disusun langkah demi langkah, dan kemudian jika Anda cenderung, beberapa penjelasan tentang bagaimana cara membuktikan / menyangkal pertanyaan sederhana seperti ini secara umum. Jika itu membantu, beberapa contoh:
[1,5,2,0,3] → (1,2,3)
[5,6,1,2,3] → (1,2,3)
[1,5,2,3] → (1,2,3)
[5,6,1,2,7] → (1,2,7)
[5,6,1,2,7,8] → (1,2,7)
[1,2,999,3] → (1,2,999)
[999,1,2,3] → (1,2,3)
[11,12,8,9,5,6,3,4,1,2,3] → (1,2,3)
[1,5,2,0,-5,-2,-1] → (-5,-2,-1)
Saya menduga bahwa orang bisa iterate atas , dan setiap kali ada (saat ini kami , yaitu), kami membuat tiga baru dan mendorongnya ke array. Kami terus melangkah dan membandingkan setiap tiga hingga satu dari tiga kali lipat kami selesai. Jadi seperti , ! Tapi saya pikir ini lebih kompleks daripada sekadar karena jumlah tiga kali lipat pada triple array kami akan dalam kasus terburuk sesuai dengan ukuran daftar input.[1,5,2,0,-5,-2,-1] → 1..2.. -5.. -2.. -1
[1,5,2,0,-5,-2,3,-1] → 1..2.. -5.. -2.. 3
sumber
Jawaban:
Ini adalah variasi dari masalah kenaikan terpanjang meningkat ; ini adalah solusi yang disajikan di Wikipedia menggunakan dua array bantu dan P :M P
Algoritma ini berjalan dalam waktu terburuk . Masalah Anda adalah kasus khusus yang memungkinkan Anda untuk kembali ketika L = 3 yang mendorong runtime ke O ( n ) karena pencarian biner hanya berjalan pada panjang array paling banyak dua, yang karena itu dalam waktu O ( 1 ) sebagai lawan dari Θ ( log n ) dalam kasus umum.Θ(nlogn) L = 3 O ( n ) O ( 1 ) Θ ( logn )
Pertimbangkan kode pseudo yang dimodifikasi:
sumber
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 < j A [ 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 ] saya A [ 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< ⋯ < im SEBUAH ).( 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 + 1 k = j + 1 A [ 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 ] saya A [ 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.saya k
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.saya j k saya
Pernyataan algoritma
Diberikan dalam sintaksis Python, tetapi berhati-hatilah karena saya belum mengujinya.
Sketsa bukti
index1
adalah indeks minimum bagian array yang telah dilalui (jika terjadi beberapa kali, kami mempertahankan kejadian pertama), atauNone
sebelum memproses elemen pertama.index2
menyimpan indeks peningkatan urutan panjang 2 di bagian array yang sudah dilintasi yang memiliki elemen terbesar terendah, atauNone
jika urutan seperti itu tidak ada.Ketika
return (index2[0], index2[1], i)
berjalan, kami memilikivalue2[0] < value[1]
(ini adalah invarian darivalue2
) danvalue[1] < A[i]
(jelas dari konteksnya). Jika loop berakhir tanpa menerapkan pengembalian awal, baikvalue1 == None
, dalam hal ini tidak ada penambahan panjang 2 panjang apalagi 3, atauvalue1
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 darivalue1
; Oleh karena itu elemen terakhir dari setiap urutan tersebut, ditambahkan kevalue2
, akan membentuk urutan berikutnya yang meningkat dari panjang 3: karena kami juga memiliki invarian yangvalue2
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
Bukti formal
Ditinggalkan sebagai latihan untuk pembaca.
sumber
Pertama, lintasi larik kiri ke kanan dengan mempertahankan tumpukan dan larik bantu yang memberi tahu Anda untuk setiap elemen, indeks elemen yang lebih besar darinya dan di sebelah kanannya.
Setiap kali Anda mempertimbangkan elemen baru dalam array, jika elemen itu lebih besar dari elemen atas stack, Anda melepaskannya dari stack, dan mengatur elemen array aux yang sesuai dengan bagian atas untuk membuat indeks elemen baru di bawah pertimbangan.
Lanjutkan mengeluarkan elemen dari tumpukan dan mengatur indeks yang sesuai, sementara elemen saat ini lebih besar. Setelah bagian atas memiliki elemen yang tidak lebih kecil (atau menjadi kosong), dorong elemen saat ini ke tumpukan, dan lanjutkan ke elemen berikutnya dari array, ulangi langkah di atas.
Buat pass lain (dan array aux lain), tetapi ke kanan ke kiri.
Kode palsu untuk pass pertama mungkin terlihat seperti ini:
sumber