Apa yang dimaksud dengan "Constant Amortized Time" ketika berbicara tentang kompleksitas waktu suatu algoritma?
algorithm
complexity-theory
big-o
VarunGupta
sumber
sumber
Jawaban:
Waktu diamortisasi dijelaskan dalam istilah sederhana:
Jika Anda melakukan operasi katakan jutaan kali, Anda tidak benar-benar peduli pada kasus terburuk atau terbaik dari operasi itu - yang Anda pedulikan adalah berapa banyak waktu yang diambil secara total ketika Anda mengulangi operasi itu sejuta kali .
Jadi tidak masalah jika operasi sangat lambat sesekali, selama "sesekali" cukup langka untuk kelambatan diencerkan. Waktu yang pada dasarnya diamortisasi berarti "waktu rata-rata yang diambil per operasi, jika Anda melakukan banyak operasi". Waktu diamortisasi tidak harus konstan; Anda dapat memiliki waktu diamortisasi linier dan logaritmik atau apa pun.
Mari kita ambil contoh mat dari array dinamis, yang berulang kali Anda tambahkan item baru. Biasanya menambahkan item membutuhkan waktu yang konstan (yaitu,
O(1)
). Tetapi setiap kali array penuh, Anda mengalokasikan dua kali lebih banyak ruang, menyalin data Anda ke wilayah baru, dan membebaskan ruang yang lama. Dengan asumsi mengalokasikan dan membebaskan berjalan dalam waktu yang konstan, proses pembesaran ini membutuhkanO(n)
waktu di mana n adalah ukuran array saat ini.Jadi setiap kali Anda memperbesar, Anda membutuhkan waktu sekitar dua kali lipat dari yang terakhir diperbesar. Tetapi Anda juga telah menunggu dua kali lebih lama sebelum melakukannya! Biaya setiap pembesaran dengan demikian dapat "tersebar" di antara sisipan. Ini berarti bahwa dalam jangka panjang, total waktu yang dibutuhkan untuk menambahkan item m ke array adalah
O(m)
, dan waktu diamortisasi (yaitu waktu per penyisipan) adalahO(1)
.sumber
Ini berarti bahwa seiring waktu, skenario terburuk akan default ke O (1), atau waktu yang konstan. Contoh umum adalah array dinamis. Jika kami telah mengalokasikan memori untuk entri baru, menambahkannya akan menjadi O (1). Jika kami belum mengalokasikannya, kami akan melakukannya dengan mengalokasikan, katakanlah, dua kali lipat jumlah saat ini. Penyisipan khusus ini bukan O (1), melainkan sesuatu yang lain.
Yang penting adalah bahwa algoritma menjamin bahwa setelah urutan operasi operasi yang mahal akan diamortisasi dan dengan demikian membuat seluruh operasi O (1).
Atau dengan istilah yang lebih ketat,
sumber
Untuk mengembangkan cara berpikir intuitif tentang hal itu, pertimbangkan penyisipan elemen dalam array dinamis (misalnya
std::vector
dalam C ++). Mari kita plot grafik, yang menunjukkan ketergantungan jumlah operasi (Y) yang diperlukan untuk memasukkan elemen N dalam array:Bagian vertikal grafik hitam sesuai dengan realokasi memori untuk memperluas array. Di sini kita dapat melihat bahwa ketergantungan ini dapat secara kasar direpresentasikan sebagai garis. Dan persamaan garis ini adalah
Y=C*N + b
(C
konstan,b
= 0 dalam kasus kami). Karena itu kita dapat mengatakan bahwa kita perlu menghabiskanC*N
operasi rata-rata untuk menambahkan elemen N ke array, atauC*1
operasi untuk menambahkan satu elemen (waktu konstan diamortisasi).sumber
Saya menemukan penjelasan Wikipedia di bawah ini bermanfaat, setelah membaca berulang sebanyak 3 kali:
Sumber: https://en.wikipedia.org/wiki/Amortized_analysis#Dynamic_Array
Untuk pemahaman saya sebagai cerita sederhana:
Anggaplah Anda memiliki banyak uang. Dan, Anda ingin menumpuknya di sebuah ruangan. Dan, Anda memiliki tangan dan kaki yang panjang, selama yang Anda butuhkan sekarang atau di masa depan. Dan, Anda harus mengisi semua dalam satu ruangan, sehingga mudah untuk menguncinya.
Jadi, Anda langsung ke ujung / sudut ruangan dan mulai menumpuknya. Saat Anda menumpuknya, perlahan ruangan akan kehabisan ruang. Namun, saat Anda mengisinya, mudah untuk menumpuknya. Dapatkan uang, masukkan uang. Mudah. Ini O (1). Kami tidak perlu memindahkan uang sebelumnya.
Begitu ruangan kehabisan ruang. Kami membutuhkan kamar lain, yang lebih besar. Di sini ada masalah, karena kita hanya dapat memiliki 1 kamar sehingga kita hanya memiliki 1 kunci, kita perlu memindahkan semua uang yang ada di ruangan itu ke kamar yang lebih besar. Jadi, pindahkan semua uang, dari kamar kecil, ke kamar yang lebih besar. Artinya, susun semuanya lagi. Jadi, Kita TIDAK perlu memindahkan semua uang sebelumnya. Jadi, itu adalah O (N). (dengan asumsi N adalah jumlah total uang dari uang sebelumnya)
Dengan kata lain, mudah sampai N, hanya 1 operasi, tetapi ketika kita perlu pindah ke ruangan yang lebih besar, kita melakukan operasi N. Jadi, dengan kata lain, jika kita kehabisan rata-rata, itu adalah 1 masukkan di awal, dan 1 lagi bergerak sambil pindah ke ruangan lain. Total 2 operasi, satu insert, satu move.
Dengan asumsi N besar seperti 1 juta bahkan di ruangan kecil, 2 operasi dibandingkan dengan N (1 juta) sebenarnya bukan angka yang sebanding, sehingga dianggap konstan atau O (1).
Dengan asumsi ketika kita melakukan semua hal di atas di ruangan lain yang lebih besar, dan sekali lagi perlu bergerak. Itu masih sama. katakanlah, N2 (katakanlah, 1 miliar) adalah jumlah baru dari jumlah uang di ruang yang lebih besar
Jadi, kami memiliki N2 (yang termasuk N dari sebelumnya karena kami memindahkan semua dari ruang kecil ke ruang lebih besar)
Kami masih membutuhkan hanya 2 operasi, satu dimasukkan ke dalam ruangan yang lebih besar, kemudian operasi pemindahan lainnya untuk pindah ke ruangan yang lebih besar.
Jadi, bahkan untuk N2 (1 miliar), itu adalah 2 operasi untuk masing-masing. yang tidak ada artinya lagi. Jadi, itu konstan, atau O (1)
Jadi, ketika N meningkat dari N ke N2, atau lainnya, itu tidak masalah. Masih konstan, atau operasi O (1) diperlukan untuk masing-masing N.
Sekarang asumsikan, Anda memiliki N sebagai 1, sangat kecil, jumlah uangnya kecil, dan Anda memiliki kamar yang sangat kecil, yang hanya akan memenuhi 1 hitungan uang.
Segera setelah Anda mengisi uang di dalam ruangan, ruangan itu terisi.
Ketika Anda pergi ke ruang yang lebih besar, anggap itu hanya dapat memuat satu uang lagi di dalamnya, total 2 hitungan uang. Itu artinya, uang yang dipindahkan sebelumnya dan 1 lagi. Dan lagi itu diisi.
Dengan cara ini, N tumbuh lambat, dan tidak ada lagi yang konstan O (1), karena kita memindahkan semua uang dari kamar sebelumnya, tetapi hanya dapat memuat 1 lebih banyak uang.
Setelah 100 kali, kamar baru tersebut cocok dengan 100 hitungan uang dari sebelumnya dan 1 lebih banyak uang yang dapat ditampungnya. Ini adalah O (N), karena O (N + 1) adalah O (N), yaitu, tingkat 100 atau 101 sama, keduanya ratusan, berbeda dengan cerita sebelumnya, satu ke jutaan dan satu ke miliaran .
Jadi, ini adalah cara yang tidak efisien dalam mengalokasikan kamar (atau memori / RAM) untuk uang kita (variabel).
Jadi, cara yang baik adalah mengalokasikan lebih banyak ruang, dengan kekuatan 2.
Ukuran kamar 1 = cocok dengan 1 hitungan uang
Ukuran kamar 2 = cocok dengan 4 hitungan uang
Ukuran kamar 3 = cocok dengan 8 jumlah uang
Ukuran kamar 4 = cocok dengan 16 jumlah uang
Ukuran kamar 5 = sesuai dengan 32 jumlah uang
6 ukuran kamar = cocok 64 hitungan uang
Ukuran kamar 7 = cocok 128 hitungan uang
Ukuran kamar 8 = cocok dengan 256 jumlah uang
Ukuran kamar ke-9 = cocok dengan 512 jumlah uang
Ukuran kamar ke-10 = cocok untuk 1024 hitungan uang
Ukuran kamar ke-11 ukuran kamar = cocok dengan jumlah uang pada 2.048
. ..
Ukuran kamar ke-16 = cocok dengan jumlah uang 65.536
...
Ukuran kamar ke-32 = cocok untuk 4.294.967.296 jumlah uang
...
Ukuran kamar ke-64 = cocok untuk jumlah uang ke 18.446.744.073.709.551.616
Kenapa ini lebih baik? Karena terlihat tumbuh lambat di awal, dan lebih cepat nanti, yaitu, dibandingkan dengan jumlah memori dalam RAM kita.
Ini bermanfaat karena, dalam kasus pertama meskipun bagus, jumlah total pekerjaan yang harus dilakukan per uang tetap (2) dan tidak sebanding dengan ukuran kamar (N), ruangan yang kami ambil pada tahap awal mungkin terlalu besar (1 juta) yang tidak dapat kita gunakan sepenuhnya tergantung pada apakah kita dapat memperoleh uang sebanyak itu untuk ditabung sama sekali dalam kasus pertama.
Namun, dalam kasus terakhir, kekuatan 2, ia tumbuh dalam batas RAM kami. Jadi, dengan meningkatkan kekuatan 2, kedua analisis Armotized tetap konstan dan ramah untuk RAM terbatas yang kita miliki saat ini.
sumber
Penjelasan di atas berlaku untuk Analisis Agregat, gagasan mengambil "rata-rata" selama beberapa operasi. Saya tidak yakin bagaimana mereka berlaku untuk metode Bankir atau Metode Fisikawan dari Analisis Amortisasi.
Sekarang. Saya tidak yakin dengan jawaban yang benar. Tapi itu harus dilakukan dengan kondisi prinsip dari kedua metode fisikawan + Bankir:
(Jumlah biaya operasi diamortisasi)> = (Jumlah biaya operasi aktual).
Kesulitan utama yang saya hadapi adalah bahwa mengingat biaya operasi amortisasi-asimptotik berbeda dari biaya normal-asimptotik, saya tidak yakin bagaimana menilai signifikansi biaya-biaya diamortisasi.
Itulah ketika seseorang memberi saya biaya yang diamortisasi, saya tahu itu tidak sama dengan biaya normal-asimptotik. Kesimpulan apa yang saya dapat dari biaya-diamortisasi itu?
Karena kami memiliki kasus beberapa operasi ditagih berlebihan sementara operasi lainnya ditagih lebih rendah, satu hipotesis bisa berupa mengutip biaya yang diamortisasi dari operasi individu akan menjadi tidak berarti.
Untuk misalnya: Untuk tumpukan fibonacci, mengutip biaya diamortisasi dari hanya Decreasing-Key menjadi O (1) tidak ada artinya karena biaya dikurangi dengan "pekerjaan yang dilakukan oleh operasi sebelumnya dalam meningkatkan potensi tumpukan".
ATAU
Kita dapat memiliki hipotesis lain yang beralasan tentang biaya perolehan diamortisasi sebagai berikut:
Saya tahu bahwa operasi yang mahal akan didahului oleh beberapa operasi BIAYA RENDAH.
Demi analisis, saya akan menjual terlalu mahal beberapa operasi berbiaya rendah, SEPERTI YANG BIAYA ASYMPTOTIC-BIAYA TIDAK BERUBAH.
Dengan peningkatan operasi berbiaya rendah ini, saya dapat MEMBUKTIKAN OPERASI EKSPENSIF yang memiliki BIAYA ASIMPTOTIK KECIL.
Jadi saya telah meningkatkan / menurunkan ASYMPTOTIC-BOUND dari biaya operasi n.
Jadi analisis biaya-diamortisasi + batas-biaya diamortisasi sekarang hanya berlaku untuk operasi mahal. Operasi yang murah memiliki biaya amortisasi asimptotik yang sama dengan biaya normal asimptotik.
sumber
Kinerja setiap fungsi dapat dirata-ratakan dengan membagi "jumlah total panggilan fungsi" menjadi "total waktu yang diambil untuk semua panggilan yang dilakukan". Bahkan fungsi yang membutuhkan waktu lebih lama dan lebih lama untuk setiap panggilan yang Anda lakukan dapat dirata-ratakan dengan cara ini.
Jadi, esensi dari fungsi yang bekerja
Constant Amortized Time
adalah bahwa "waktu rata-rata" ini mencapai langit-langit yang tidak dapat dilampaui karena jumlah panggilan terus meningkat. Setiap panggilan tertentu dapat bervariasi dalam kinerja, tetapi dalam jangka panjang waktu rata-rata ini tidak akan terus tumbuh semakin besar.Ini adalah kelebihan penting dari sesuatu yang tampil di
Constant Amortized Time
.sumber