dalam O (n) waktu: Temukan elemen terbesar di set di mana perbandingan tidak transitif

21

Judul menyatakan pertanyaan.

Kami memiliki sebagai input daftar elemen, yang dapat kami bandingkan (menentukan mana yang terbesar ). Tidak ada elemen yang bisa sama.

Poin-poin penting:

  1. Perbandingannya bukan transitif (pikirkan gunting kertas batu): ini bisa benar: A> B, B> C, C> A (perhatikan ini bukan input yang valid karena tidak ada jawaban yang valid di sini, saya hanya menjelaskan apa " perbandingan non-transitif "berarti)
  2. Setiap input array akan dijamin memiliki jawaban
  3. terbesar berarti elemen harus lebih besar daripada setiap elemen lainnya
  4. Properti Converse memegang yaitu A> B menyiratkan bahwa B <A

Contoh:

Input: [A,B,C,D]
A > B, B > C, C > A
D > A, D > B, D > C
Output: D

Saya tidak dapat menemukan cara untuk melakukan ini dalam waktu O (n), solusi terbaik saya adalah O (n ^ 2).

Saya terjebak pada setiap pendekatan karena fakta bahwa untuk memastikan jawaban, elemen tersebut harus secara eksplisit dibandingkan dengan setiap elemen lainnya, untuk membuktikannya memang jawabannya (karena perbandingannya tidak transitif).

Ini mengesampingkan penggunaan tumpukan, penyortiran, dll.

James Wierzba
sumber
8
Tidak jelas bagaimana "elemen terbesar" akan didefinisikan? Misalnya, elemen mana yang paling besar jika ? Apakah Anda memiliki aturan perbandingan lain? A>B,B>C,C>A
fade2black
6
Saya tidak bisa membayangkan bagaimana kita akan memilih elemen terbesar dalam set yang setidaknya tidak dipesan sebagian. Silakan lihat definisi elemen terbesar dan terkecil. Kurangnya transitivitas mengesampingkan urutan parsial.
fade2black
3
@ fade2black Mengapa Anda menautkan saya ke definisi "terhebat" lainnya. Saya secara eksplisit menyatakan definisi terbesar untuk konteks pertanyaan ini. Berarti terbesar, elemen lebih besar dari setiap elemen lainnya. Tidak ada elemen yang sama. Hanya itu yang ada untuk itu. Apakah ini tidak jelas?
James Wierzba
2
Contoh terakhir Anda dengan A, B, C, D akan sangat membantu untuk memahami pertanyaan Anda jika Anda memasukkannya ke dalam OP Anda.
fade2black
3
Seorang anggota tim penyusun C # biasa menanyakan ini sebagai pertanyaan wawancara; ini relevan karena dalam C #, algoritma resolusi kelebihan beban harus memilih anggota terbaik yang unik dari suatu himpunan yang diberi relasi "betterness" yang biasanya, tetapi tidak harus transitif. (Atau memberikan tanggapan yang sesuai jika tidak ada anggota terbaik yang unik; ikatan mungkin.) Meskipun saya berhasil menjawabnya dengan benar, saya tidak pernah berpikir itu adalah pertanyaan wawancara yang sangat baik karena bergantung pada wawasan "aha" untuk mendapatkan algoritma linier.
Eric Lippert

Jawaban:

38

Algoritma standar untuk menemukan maksimum masih berfungsi. Mulailah dengan dan pergi ke elemen, jika Anda melihat nilai yang lebih besar, memperbarui maksimal menjadi nilai itu. Alasan ini berfungsi adalah bahwa setiap elemen yang Anda lewati lebih kecil dari setidaknya satu elemen, dan dengan demikian tidak dapat menjadi maksimum.a1

Agar lebih jelas, dengan "algoritma standar" yang saya maksud adalah sebagai berikut:

max <- a_1
for i=2 to n
   if a_i > max
      max <- a_i
output max

Untuk kelengkapan, saya akan membahas di sini masalah yang diangkat dalam komentar. Pengaturan dalam diskusi di atas adalah menemukan maksimum relatif terhadap relasi simetris anti , di mana sebuah i adalah maksimum jika untuk semua j i kita memiliki sebuah i<aiji . Algoritme di atas bekerja dengan asumsi bahwa ada maksimum, tetapi jika ini tidak diketahui, seseorang dapat menggunakannya untuk memverifikasi keberadaan maksimum (memeriksa apakah elemen yang dikembalikan memang lebih besar dari semua elemen lain, ini disebutkan dalam komentar Chi dan jawaban Ilmari Karonen).ai>aj

Jika belum tentu anti simetris, maka algoritma di atas gagal (seperti yang disebutkan Emil dalam komentar). Jika < adalah hubungan yang arbitrer (yaitu kita bersantai baik transitivitas dan anti simetri), maka tidak sulit untuk menunjukkan bahwa menemukan maksimum dalam waktu linear tidak mungkin. Dilambangkan dengan # yang saya jumlah kali sebuah i berpartisipasi dalam query, kita mendefinisikan sebuah hubungan bermusuhan dengan cara yang maksimal tidak dapat diungkapkan tanpa permintaan yang cukup. Mengingat permintaan sebuah i > ? a j , menjawab sebuah i > a j jika # sebuah i<<#aiaiai>?ajai>aj ) , maka maksimum belum terlihat, dan dapat diatur menjadi salah satu elemen dalam himpunan.#ai<n1dan sebaliknya. Jika jumlah kueri adalah o ( n 2ai<ajHai(n2)

Ariel
sumber
1
@ JamesWierzba (saya pikir) dia hanya berarti elemen "dilewati" adalah salah satu yang tidak lebih besar dari maks Anda saat ini. Pertimbangkan algoritma standar: Anda memeriksa setiap nilai dalam daftar Anda terhadap maksimum saat ini. Anda sudah mengatakan ada elemen terbesar di setiap daftar. Pada titik tertentu, Anda akan membandingkannya dengan maksimum saat ini, dan karena lebih besar, nilai itu menjadi maksimum baru Anda. Karena nilai ini lebih besar dari semua yang ada dalam daftar, Anda tidak akan pernah menemukan elemen yang lebih besar, dan nilai terbesar Anda tidak akan diganti. Setelah nperbandingan Anda , maks Anda saat ini harus menjadi jawaban
Lord Farquaad
1
Diedit untuk kejelasan, algoritma ini tidak menganggap transitivitas. Jika Anda merasa sulit untuk percaya, ikuti detail bukti kebenaran (anggaplah untuk tujuan kontradiksi bahwa nilai yang dikembalikan tidak maksimal, dan gunakan ide dari paragraf pertama).
Ariel
7
Ini bergantung pada asumsi 2 dalam pertanyaan: selalu ada maksimum dalam array. Jika ini bukan masalahnya, maxhanya bisa maksimum subarray. Namun, bahkan tanpa asumsi 2, seseorang dapat menemukan maksimum tentatif, dan kemudian memverifikasi pada seluruh array menggunakan pemindaian kedua, dalam batas O (n).
chi
7
Jawaban ini mengasumsikan bahwa dan B > A tidak dapat bertahan pada saat yang sama. Sejauh yang saya bisa lihat, ini tidak dikesampingkan dalam pertanyaan. A>BB>A
Emil Jeřábek mendukung Monica
4
@ oconnor0 Itu tidak mengikuti. Untuk contoh konkret, asumsikan A> B, A> C, B> A, dan C> B. Kemudian A lebih besar daripada elemen lain di set (dan merupakan satu-satunya elemen dengan properti ini), tetapi jika elemen tersebut adalah ditemui dalam urutan A, B, C, algoritma akan menampilkan C.
Emil Jeřábek mendukung Monica
24

Seperti yang dicatat Ariel , algoritma pencarian maksimum standar yang diberikan di bawah ini:

def find_maximum(a):
    m = a[0]
    for x in a:
        if x > m: m = x
    return m

sebenarnya akan bekerja tanpa modifikasi selama:

  • setiap pasangan elemen dapat dibandingkan, dan
  • input dijamin mengandung elemen maksimal, yaitu elemen yang berpasangan lebih besar dari elemen lain dalam input.

(Asumsi pertama di atas sebenarnya dapat dilonggarkan, bahkan tanpa harus memodifikasi algoritme, asalkan kita mengasumsikan bahwa elemen maksimal sebanding dengan setiap elemen lainnya dan itu x > yselalu salah jika elemenx dan ytidak .)

Secara khusus, klaim Anda bahwa:

[...] untuk memastikan jawaban, elemen tersebut harus secara eksplisit dibandingkan dengan setiap elemen lainnya (karena perbandingan tidak transitif).

tidak benar berdasarkan asumsi yang diberikan di atas. Bahkan, untuk membuktikan bahwa algoritma di atas akan selalu menemukan elemen maksimal, cukup untuk mengamati bahwa:

  1. karena loop berulang pada semua elemen input, pada beberapa iterasi x akan menjadi elemen maksimal;
  2. karena elemen maksimal berpasangan lebih besar daripada elemen lainnya, maka pada akhirnya iterasi makan menjadi elemen maksimal; dan
  3. karena tidak ada elemen lain yang bisa berpasangan lebih besar dari elemen maksimal, maka mtidak akan berubah pada iterasi berikutnya.

Oleh karena itu, pada akhir loop, makan selalu menjadi elemen maksimal, jika inputnya mengandung satu.


Ps. Jika input tidak selalu selalu mengandung elemen maksimal, maka memverifikasi fakta itu memang akan membutuhkan pengujian jawaban kandidat terhadap setiap elemen lainnya untuk memverifikasi bahwa itu benar-benar maksimal. Namun, kami masih dapat melakukannya dalam waktu O ( n ) setelah menjalankan algoritma pencarian maksimum di atas:

def find_maximum_if_any(a):
    # step 1: find the maximum, if one exists
    m = a[0]
    for x in a:
        if x > m: m = x

    # step 2: verify that the element we found is indeed maximal
    for x in a:
        if x > m: return None  # the input contains no maximal element
    return m  # yes, m is a maximal element

(Saya berasumsi di sini bahwa hubungannya >tidak refleksif, yaitu tidak ada elemen yang bisa lebih besar dari dirinya sendiri. Jika itu belum tentu demikian, perbandingan x > mpada langkah 2 harus diganti dengan x ≠ m and x > m, di mana menunjukkan perbandingan identitas. Atau kita bisa menerapkan optimasi tercantum di bawah ini.)

Untuk membuktikan kebenaran variasi algoritma ini, pertimbangkan dua kemungkinan kasus:

  • Jika input berisi elemen maksimal, maka langkah 1 akan menemukannya (seperti yang ditunjukkan di atas) dan langkah 2 akan mengkonfirmasinya.
  • Jika input tidak mengandung elemen maksimal, maka langkah 1 akan memilih elemen arbitrer sebagai m. Tidak masalah elemen mana itu, karena dalam hal apa pun akan menjadi non-maksimal, dan karenanya langkah 2 akan mendeteksi itu dan kembali None.

Jika kita disimpan indeks dari mdalam array masukan a, kita bisa benar-benar mengoptimalkan langkah 2 hanya memeriksa unsur-unsur yang datang sebelum mdi a, karena setiap elemen kemudian telah dibandingkan dengan mpada langkah 1. Tapi optimasi ini tidak mengubah kompleksitas waktu asimptotik dari algoritma, yang masih O ( n ).

Ilmari Karonen
sumber
3
Bahkan OP melewatkan banyak detail. Misalnya, tidak ada yang dikatakan tentang refleksivitas hubungan, dan jadi jika tidak refleksif maka if x > m:tidak didefinisikan.
fade2black
4

"Terbesar berarti elemen harus lebih besar daripada setiap elemen lainnya" adalah petunjuk besar tentang bagaimana melakukan ini di .O(n)

Jika Anda menelusuri daftar elemen pembanding, elemen apa pun yang "kehilangan" perbandingan dapat segera dibuang karena, agar menjadi yang terbesar, elemen tersebut harus lebih besar daripada SEMUA elemen lainnya sehingga kerugian tunggal mendiskualifikasi itu.

n1

Solusi ini diaktifkan oleh kehalusan: "Tidak ada elemen yang bisa sama" dikombinasikan dengan fakta bahwa akan selalu ada elemen terbesar. Jika kita memetakan hubungan win sebagai grafik terarah, jelas bahwa kita dapat mencapai elemen terbesar hanya dengan mengikuti kemenangan.

Danikov
sumber
1
" Grafik diarahkan asiklik " adalah model yang salah: ia seharusnya menjadi " turnamen ". Siklus diizinkan, dan sangat penting bahwa setiap sisi ada tepat satu arah.
Peter Taylor
@PeterTaylor Anda benar sekali, saya hanya berpikir tentang kemenangan yang mengarah ke elemen 'terhebat', kemenangan lain kurang relevan tetapi mungkin dilalui di jalan untuk menemukan yang terbaik sehingga Anda benar bahwa mereka bisa ' t didiskon
Danikov
3

Saya berasumsi bahwa hubungan antisimetris untuk setidaknya satu elemen (yang menjamin keberadaan elemen terbesar), jika tidak tugas itu tidak mungkin. Jika semua elemen dalam himpunan terbatas dapat diperbandingkan, maka prosedur penemuan-maksimum biasanya berfungsi.

Jika beberapa elemen tidak sebanding maka prosedur berikut ini akan berhasil

max = nil
For i=1 to n
   if max is nil then
      max = a[i]
   if max and a[i] are not comparable then
      max = nil
   else if max < a[i] then
      max = a[i]
End

A,B,C,D

A>B,B>C,C>A
D>A,D>B,D>C


i=1: max=A
i=2: max=AA>B
i=3: max=CA<C
i=4: max=DD>C

m>aa<mamm<aamam

fade2black
sumber
Saya tidak berpikir yang pertama else ifdiperlukan. Tidak dapat dipicu jikamax maksimum, dan jika maksimum belum ditemukan tidak peduli berapa nilainya max.
rici
Ya, itu yang pertama. Yang lain adalah yang kedua :)
rici
Maksudmu pergi iftanpa tanpa else? Itu hanya kebiasaan: dengan elsekita bahkan tidak bisa dibandingkan. :)
fade2black
1
Bukankah lebih mudah untuk hanya menginisialisasi maxke elemen daftar dan, di dalam loop, lakukanif max and a[i] are comparable and max < a[i] then max = a[i] (di mana bagian pertama dari kondisi dapat dihilangkan jika kita berasumsi bahwa mencoba membandingkan dua elemen yang tak tertandingi selalu menghasilkan false)?
Ilmari Karonen
1
@badallen OP berasumsi bahwa selalu ada elemen terbesar. Dalam contoh Anda tidak ada elemen terbesar.
fade2black
2

SEBUAH<BB<SEBUAH

SEBUAH1...SEBUAHn. Algoritme Anda akan di setiap langkah kueriSEBUAHsaya<SEBUAHjuntuk beberapa pasangan i dan j. Tidak masalah di mana urutan Anda meminta mereka, selalu ada hubungan di mana Anda harus meminta semua hubungan sebelum menemukan maksimum. Alasan untuk ini paling baik dijelaskan dengan mengasumsikan Anda memiliki musuh yang dapat mengubah masalah saat algoritma Anda berjalan.

(Perhatikan bahwa argumen tidak tergantung pada apa yang sebenarnya dilakukan algoritma dengan informasi yang didapatnya tentang elemen, karena itu menjelaskan bahwa ia tidak dapat mengetahui bahwa suatu elemen sudah maksimal sebelum membuat n2 pertanyaan.)

Untuk sebagian besar algoritma, musuh akan memastikan untuk selalu mengembalikan true untuk SEBUAHsaya<SEBUAHj sampai permintaan terakhir Anda diberikan j. Perhatikan bahwa Anda tidak dapat mengetahui bahwa satu elemen yang diberikan adalah maksimal sampai Anda membandingkannya dengan semua elemen lainnya. Hanya untuk elemen terakhir yang Anda selesaikan semua relasi musuh akan mengembalikan true untuk elemen terakhir juga.

Relasi yang dihasilkan akan selalu sedemikian rupa sehingga ada beberapa j0 untuk itu SEBUAHsaya<SEBUAHj0saya dan untuk semua lainnya j akan ada beberapa sayaj seperti yang SEBUAHsaya<SEBUAHjsayasayaj dan kita tidak akan punya SEBUAHsayaj<SEBUAHj. Musuh memilihj0 dan sayajtergantung pada algoritma Anda.

Saya harap ini agak bisa dimengerti. Jangan ragu untuk bertanya dalam komentar atau mengedit.

Ide dasarnya adalah bahwa Anda tidak dapat mengumpulkan informasi tentang elemen yang tersisa dari yang sudah Anda ketahui jika Anda mengizinkan hubungan yang sepenuhnya sewenang-wenang.

Argumen itu masih berfungsi jika kita tidak mengizinkan SEBUAH<SEBUAH. Kami hanya akan menghematn pertanyaan seperti itu dan masih perlu n2-n.

Corinna
sumber
1

Saya akan menipu dan memanggil nomor A > Bentrin dan Anda perlu melihat setiap entri setidaknya sekali.

Dengan cara itu Anda dapat mengulangi hanya entri dan menghapus elemen yang kurang dari yang lain dari sekumpulan solusi yang mungkin. Dengan hashset atau yang serupa ini dimungkinkan diHAI(n)

ratchet freak
sumber