EDIT: Ini gagal dalam batasan "ruang konstan" - pada dasarnya menggandakan ruang yang diperlukan. Saya sangat meragukan bahwa ada solusi yang tidak melakukan itu, tanpa merusak kompleksitas runtime di suatu tempat (misalnya membuat push / pop O (n)). Perhatikan bahwa ini tidak mengubah kompleksitas ruang yang diperlukan, misalnya jika Anda memiliki tumpukan dengan persyaratan ruang O (n), ini akan tetap menjadi O (n) hanya dengan faktor konstanta yang berbeda.
Solusi ruang non-konstan
Jaga agar tumpukan "duplikat" dari "minimal semua nilai lebih rendah dalam tumpukan". Saat Anda meletuskan tumpukan utama, keluarkan juga tumpukan min. Saat Anda mendorong tumpukan utama, dorong elemen baru atau min saat ini, mana saja yang lebih rendah. getMinimum()
kemudian diimplementasikan sebagai adil minStack.peek()
.
Jadi dengan menggunakan contoh Anda, kami memiliki:
Real stack Min stack
5 --> TOP 1
1 1
4 2
6 2
2 2
Setelah muncul dua kali Anda mendapatkan:
Real stack Min stack
4 2
6 2
2 2
Tolong beri tahu saya jika informasi ini tidak cukup. Sederhana saja ketika Anda mengelusnya, tetapi mungkin akan sedikit menggaruk-garuk kepala pada awalnya :)
(Kelemahannya tentu saja adalah bahwa hal itu menggandakan kebutuhan ruang. Waktu eksekusi tidak terpengaruh secara signifikan - yaitu masih kompleksitas yang sama.)
EDIT: Ada variasi yang sedikit lebih rumit, tetapi memiliki ruang yang lebih baik secara umum. Kami masih memiliki tumpukan min, tetapi kami hanya muncul darinya ketika nilai yang kami keluarkan dari tumpukan utama sama dengan yang ada di tumpukan min. Kami hanya mendorong ke tumpukan minimum ketika nilai yang didorong ke tumpukan utama kurang dari atau sama dengan nilai min saat ini. Ini memungkinkan duplikat nilai min. getMinimum()
masih hanya operasi intip. Misalnya, mengambil versi asli dan mendorong 1 lagi, kita akan mendapatkan:
Real stack Min stack
1 --> TOP 1
5 1
1 2
4
6
2
Muncul dari atas muncul dari kedua tumpukan karena 1 == 1, meninggalkan:
Real stack Min stack
5 --> TOP 1
1 2
4
6
2
Muncul lagi hanya muncul dari tumpukan utama, karena 5> 1:
Real stack Min stack
1 1
4 2
6
2
Muncul lagi memunculkan kedua tumpukan karena 1 == 1:
Real stack Min stack
4 2
6
2
Ini berakhir dengan kompleksitas ruang kasus terburuk yang sama (menggandakan tumpukan asli) tetapi penggunaan ruang yang jauh lebih baik jika kita jarang mendapatkan "minimum baru atau sama".
EDIT: Berikut implementasi skema jahat Pete. Saya belum mengujinya secara menyeluruh, tapi menurut saya tidak apa-apa :)
using System.Collections.Generic;
public class FastMinStack<T>
{
private readonly Stack<T> stack = new Stack<T>();
// Could pass this in to the constructor
private readonly IComparer<T> comparer = Comparer<T>.Default;
private T currentMin;
public T Minimum
{
get { return currentMin; }
}
public void Push(T element)
{
if (stack.Count == 0 ||
comparer.Compare(element, currentMin) <= 0)
{
stack.Push(currentMin);
stack.Push(element);
currentMin = element;
}
else
{
stack.Push(element);
}
}
public T Pop()
{
T ret = stack.Pop();
if (comparer.Compare(ret, currentMin) == 0)
{
currentMin = stack.Pop();
}
return ret;
}
}
Tambahkan bidang untuk menampung nilai minimum dan perbarui selama Pop () dan Push (). Dengan cara itu getMinimum () akan menjadi O (1), tetapi Pop () dan Push () harus melakukan lebih banyak pekerjaan.
Jika nilai minimum muncul, Pop () akan menjadi O (n), jika tidak, keduanya akan tetap menjadi O (1). Saat mengubah ukuran Push () menjadi O (n) sesuai dengan implementasi Stack.
Berikut implementasi cepatnya
sumber
Ini menyimpan minimum saat ini secara eksplisit, dan jika minimum berubah, alih-alih mendorong nilai, itu mendorong nilai perbedaan yang sama di sisi lain dari minimum baru (jika min = 7 dan Anda mendorong 5, itu mendorong 3 sebagai gantinya (5- | 7-5 | = 3) dan set min ke 5; jika Anda kemudian meletuskan 3 ketika min adalah 5, terlihat bahwa nilai yang muncul kurang dari min, jadi membalikkan prosedur untuk mendapatkan 7 untuk min baru, lalu mengembalikan yang sebelumnya min). Karena nilai apa pun yang tidak menyebabkan perubahan, minimum saat ini lebih besar dari minimum saat ini, Anda memiliki sesuatu yang dapat digunakan untuk membedakan antara nilai yang mengubah minimum dan yang tidak.
Dalam bahasa yang menggunakan bilangan bulat ukuran tetap, Anda meminjam sedikit ruang dari representasi nilai, sehingga mungkin kurang dan pernyataan akan gagal. Namun sebaliknya, ruang ekstra konstan dan semua operasi tetap O (1).
Tumpukan yang didasarkan pada daftar tertaut memiliki tempat lain yang dapat Anda pinjam sedikit, misalnya di C bit paling tidak signifikan dari penunjuk berikutnya, atau di Java, tipe objek dalam daftar tertaut. Untuk Java, ini berarti ada lebih banyak ruang yang digunakan dibandingkan dengan tumpukan yang berdekatan, karena Anda memiliki overhead objek per tautan:
Di C, overhead tidak ada, dan Anda dapat meminjam lsb dari pointer berikutnya:
Namun, tidak satupun dari ini benar-benar O (1). Mereka tidak memerlukan ruang lagi dalam praktiknya, karena mereka mengeksploitasi lubang dalam representasi angka, objek, atau penunjuk dalam bahasa ini. Tetapi mesin teoritis yang menggunakan representasi yang lebih kompak akan membutuhkan sedikit tambahan untuk ditambahkan ke representasi itu dalam setiap kasus.
sumber
pop()
jika nilai terakhir yang didorong adalahInteger.MIN_VALUE
(misalnya, push 1, push Integer.MIN_VALUE, pop). Hal ini disebabkan karena kekurangan aliran listrik seperti yang disebutkan di atas. Jika tidak, berfungsi untuk semua nilai integer.Saya menemukan solusi yang memenuhi semua batasan yang disebutkan (operasi waktu konstan) dan ruang ekstra konstan .
Idenya adalah untuk menyimpan selisih antara nilai min dan angka masukan, dan memperbarui nilai min jika tidak lagi minimum.
Kodenya adalah sebagai berikut:
Kredit diberikan ke: https://leetcode.com/discuss/15679/share-my-java-solution-with-only-one-stack
sumber
Nah, apa saja batasan waktu proses
push
danpop
? Jika mereka tidak harus konstan, maka hitung saja nilai minimum dalam dua operasi tersebut (menjadikannya O ( n )). Jika tidak, saya tidak melihat bagaimana ini bisa dilakukan dengan ruang tambahan yang konstan.sumber
Ini Kode saya yang berjalan dengan O (1). Kode sebelumnya yang saya posting mengalami masalah ketika elemen minimum muncul. Saya mengubah kode saya. Yang ini menggunakan Tumpukan lain yang mempertahankan elemen minimum yang ada dalam tumpukan di atas elemen yang didorong saat ini.
sumber
Saya menggunakan jenis tumpukan yang berbeda. Berikut implementasinya.
Keluaran:
Cobalah. Saya pikir itu menjawab pertanyaan itu. Elemen kedua dari setiap pasangan memberikan nilai minimum yang terlihat saat elemen itu dimasukkan.
sumber
Saya memposting kode lengkap di sini untuk menemukan min dan max dalam tumpukan yang diberikan.
Kompleksitas waktu akan menjadi O (1) ..
Beri tahu saya jika Anda menghadapi masalah apa pun
Terima kasih, Vikash
sumber
Anda dapat memperluas kelas tumpukan asli Anda dan menambahkan pelacakan minimum ke dalamnya. Biarkan kelas induk asli menangani yang lainnya seperti biasa.
sumber
Ini solusi saya di java menggunakan daftar suka.
}
sumber
Mari kita asumsikan tumpukan yang akan kita kerjakan adalah ini:
Pada representasi di atas stack hanya dibangun oleh nilai kiri [nilai min] nilai kanan ditulis hanya untuk tujuan ilustrasi yang akan disimpan dalam satu variabel.
Masalah sebenarnya adalah ketika nilai yang merupakan nilai minimum dihapus pada titik itu bagaimana kita bisa mengetahui apa elemen minimum berikutnya tanpa iterasi di atas tumpukan.
Seperti misalnya di tumpukan kami ketika 6 get muncul, kami tahu bahwa, ini bukan elemen minimum karena elemen minimumnya adalah 2, jadi kami dapat menghapus ini dengan aman tanpa memperbarui nilai min kami.
Tetapi ketika kita memunculkan 2, kita dapat melihat bahwa nilai minimumnya adalah 2 sekarang dan jika ini muncul maka kita perlu memperbarui nilai minimum menjadi 3.
Point1:
Sekarang jika Anda mengamati dengan seksama kita perlu menghasilkan nilai min = 3 dari keadaan tertentu ini [2, nilai minimum = 2]. atau jika Anda menggunakan tumpukan, kami perlu menghasilkan nilai minimum = 7 dari keadaan tertentu ini [3, nilai minimum = 3] atau jika Anda lebih depper dalam tumpukan maka kita perlu menghasilkan nilai minimum = 8 dari keadaan tertentu ini [7, nilai minimum = 7]
Apakah Anda melihat sesuatu yang sama dalam semua 3 kasus di atas, nilai yang perlu kita hasilkan bergantung pada dua variabel yang keduanya sama. Benar. Mengapa ini terjadi karena ketika kita mendorong beberapa elemen lebih kecil dari nilai min saat ini, maka pada dasarnya kita mendorong elemen itu ke dalam tumpukan dan memperbarui nomor yang sama di nilai min juga.
Point2:
Jadi pada dasarnya kita menyimpan duplikat dari nomor yang sama sekali dalam tumpukan dan sekali dalam variabel nilai kecil. Kita perlu fokus untuk menghindari duplikasi ini dan menyimpan data yang berguna dalam tumpukan atau nilai minimum untuk menghasilkan nilai minimum sebelumnya seperti yang ditunjukkan dalam KASUS di atas.
Mari kita fokus pada apa yang harus kita simpan dalam tumpukan ketika nilai yang akan disimpan dalam push kurang dari nilai minmum. Beri nama variabel ini y, jadi sekarang tumpukan kita akan terlihat seperti ini:
Saya telah mengganti namanya menjadi y1, y2, y3 untuk menghindari kebingungan bahwa semuanya akan memiliki nilai yang sama.
Point3:
Sekarang Mari kita coba mencari beberapa batasan di atas y1, y2 dan y3. Apakah Anda ingat kapan tepatnya kita perlu mengupdate minvalue saat melakukan pop (), hanya ketika kita telah memunculkan elemen yang sama dengan minvalue. Jika kita memunculkan sesuatu yang lebih besar dari nilai min, maka kita tidak perlu memperbarui nilai min. Jadi untuk memicu pembaruan nilai min, y1, y2 & y3 harus lebih kecil daripada nilai min yang sesuai. [Kami menghindari persamaan untuk menghindari duplikasi [Titik2]] sehingga batasannya adalah [y <nilai min].
Sekarang mari kembali ke mengisi y, kita perlu menghasilkan beberapa nilai dan meletakkan y pada saat mendorong, ingat. Mari kita ambil nilai yang akan datang untuk mendorong menjadi x yang kurang dari nilai prevMinvalue, dan nilai yang sebenarnya akan kita dorong dalam tumpukan menjadi y. Jadi satu hal yang jelas bahwa newMinValue = x, dan y <newMinvalue.
Sekarang kita perlu menghitung y (ingat y bisa berupa angka apa saja yang kurang dari newMinValue (x) jadi kita perlu mencari beberapa angka yang bisa memenuhi batasan kita) dengan bantuan prevMinvalue dan x (newMinvalue).
Jadi pada saat menekan x jika kurang dari prevMinvalue maka kami mendorong y [2 * x-prevMinValue] dan memperbarui newMinValue = x.
Dan pada saat pop jika stack berisi sesuatu yang kurang dari minValue maka itulah pemicu kami untuk memperbarui minVAlue. Kita harus menghitung prevMinValue dari curMinValue dan y. y = 2 * curMinValue - prevMinValue [Terbukti] prevMinVAlue = 2 * curMinvalue - y.
2 * curMinValue - y adalah angka yang perlu kita perbarui sekarang ke prevMinValue.
Kode untuk logika yang sama dibagikan di bawah ini dengan kompleksitas O (1) waktu dan O (1) ruang.
sumber
Ini adalah versi implementasi saya.
sumber
sumber
Saya menemukan solusi ini di sini
sumber
sumber
sumber
sumber
Ini Kode saya yang berjalan dengan O (1). Di sini saya menggunakan pasangan vektor yang berisi nilai yang didorong dan juga berisi nilai minimum hingga nilai yang didorong ini.
Ini adalah versi implementasi C ++ saya.
sumber
sumber
Class
-MinStack
? Dokumentasi Java Oracle menyarankan untuk digunakanDeque
.Implementasi praktis untuk menemukan nilai minimum dalam Tumpukan Objek yang Dirancang Pengguna, bernama: Sekolah
Stack akan menyimpan Sekolah di Stack berdasarkan peringkat yang ditetapkan ke sekolah di wilayah tertentu, katakanlah, findMin () memberikan Sekolah tempat kami mendapatkan jumlah maksimum aplikasi untuk Penerimaan, yang pada gilirannya akan ditentukan oleh pembanding yang menggunakan peringkat yang terkait dengan sekolah di musim sebelumnya.
Juga Objek Sekolah adalah sebagai berikut:
Contoh ini mencakup hal-hal berikut: 1. Implementasi Stack untuk Objek yang Ditentukan Pengguna, di sini, Sekolah 2. Implementasi untuk metode hashcode () dan equals () menggunakan semua bidang Objek yang akan dibandingkan 3. Implementasi praktis untuk skenario di mana kita rqeuire untuk mendapatkan operasi Stack berisi agar berada di urutan O (1)
sumber
language-agnostic
harap sebutkan apa yang Anda gunakan untuk kode tersebut (dan hapus yang kosong sebelumnyaThe Code for same is below:
.) Bagaimana ini mendukungstack.pop()
? (danpush()
?)Berikut implementasi PHP yang dijelaskan dalam jawaban Jon Skeet sebagai implementasi kompleksitas ruang yang sedikit lebih baik untuk mendapatkan tumpukan maksimum dalam O (1).
sumber
Berikut adalah implementasi C ++ dari Jon Skeets Answer . Ini mungkin bukan cara yang paling optimal untuk mengimplementasikannya, tetapi melakukan persis seperti yang seharusnya.
Dan inilah pengemudi untuk kelasnya
Keluaran:
sumber
Kita dapat melakukan ini dalam kompleksitas ruang O (n) waktu dan O (1), seperti:
sumber
Saya pikir Anda cukup menggunakan LinkedList dalam implementasi stack Anda.
Pertama kali Anda memasukkan nilai, Anda meletakkan nilai ini sebagai kepala linkedlist.
maka setiap kali Anda push nilai, jika nilai baru <head.data, lakukan operasi prepand (yang berarti head menjadi nilai baru)
jika tidak, maka lakukan operasi penambahan.
Saat Anda membuat pop (), Anda memeriksa apakah min == linkedlist.head.data, jika ya, maka head = head.next;
Ini kode saya.
sumber
sumber
sumber
Lihat solusi brilian di sini: https://www.geeksforgeeks.org/design-a-stack-that-supports-getmin-in-o1-time-and-o1-extra-space/
Di bawah ini adalah kode python yang saya tulis dengan mengikuti algoritme:
sumber
Untuk mendapatkan elemen dari Stack. Kita harus menggunakan Two stack .ie Stack s1 dan Stack s2.
--------------------- Panggil Langkah 2 ke 4 secara rekursif -----------------------
jika elemen baru ditambahkan ke tumpukan s1. Kemudian elemen pop dari tumpukan s2
bandingkan elemen baru dengan s2. mana yang lebih kecil, dorong ke s2.
pop dari stack s2 (yang berisi elemen min)
Kode terlihat seperti:
sumber
Saya pikir hanya operasi push yang menderita, sudah cukup. Implementasi saya mencakup setumpuk node. Setiap node berisi item data dan juga minimum pada saat itu. Minimum ini diperbarui setiap kali operasi dorong dilakukan.
Berikut beberapa poin untuk dipahami:
Saya mengimplementasikan tumpukan menggunakan Linked List.
Bagian atas penunjuk selalu mengarah ke item yang terakhir didorong. Ketika tidak ada item di atas tumpukan itu adalah NULL.
Ketika sebuah item didorong, sebuah simpul baru dialokasikan yang memiliki penunjuk berikutnya yang menunjuk ke tumpukan sebelumnya dan atas diperbarui untuk menunjuk ke simpul baru ini.
Satu-satunya perbedaan dengan implementasi tumpukan normal adalah bahwa selama push, pembaruan minimum anggota untuk node baru.
Silakan lihat kode yang diimplementasikan di C ++ untuk tujuan demonstrasi.
Dan keluaran dari program tersebut terlihat seperti ini:
sumber
sumber