Mencari Elemen K Teratas dalam Array Java

1. Gambaran keseluruhan

Dalam tutorial ini, kami akan melaksanakan penyelesaian yang berbeza untuk masalah mencari unsur k terbesar dalam array dengan Java. Untuk menggambarkan kerumitan masa, kita akan menggunakan notasi Big-O.

2. Penyelesaian Brute-Force

Penyelesaian brute-force untuk masalah ini adalah untuk Itekadar melalui pelbagai diberikan k kali . Dalam setiap lelaran, kami akan menemui nilai terbesar . Kemudian kami akan membuang nilai ini dari array dan dimasukkan ke dalam senarai output:

public List findTopK(List input, int k) { List array = new ArrayList(input); List topKList = new ArrayList(); for (int i = 0; i < k; i++) { int maxIndex = 0; for (int j = 1; j  array.get(maxIndex)) { maxIndex = j; } } topKList.add(array.remove(maxIndex)); } return topKList; }

Sekiranya kita anggap n sebagai ukuran array yang diberikan, kerumitan masa penyelesaian ini adalah O (n * k) . Tambahan pula, ini adalah penyelesaian yang paling tidak cekap.

3. Pendekatan Koleksi Java

Walau bagaimanapun, penyelesaian yang lebih berkesan untuk masalah ini ada. Di bahagian ini, kami akan menerangkan dua daripadanya menggunakan Koleksi Java.

3.1. Set Pokok

TreeSet mempunyai struktur data Pohon Merah-Hitam sebagai tulang belakang. Akibatnya, meletakkan nilai pada set ini berharga O (log n) . TreeSet adalah koleksi yang disusun. Oleh itu, kita dapat meletakkan semua nilai di TreeSet dan mengekstrak k pertama dari mereka:

public List findTopK(List input, int k) { Set sortedSet = new TreeSet(Comparator.reverseOrder()); sortedSet.addAll(input); return sortedSet.stream().limit(k).collect(Collectors.toList()); }

Yang masa kerumitan penyelesaian ini adalah O (n * log n) . Yang terpenting, ini seharusnya lebih efisien daripada pendekatan brute-force sekiranya k ≥ log n .

Penting untuk diingat bahawa TreeSet tidak mengandungi pendua. Hasilnya, penyelesaiannya hanya berfungsi untuk array input dengan nilai yang berbeza.

3.2. KeutamaanQueue

PriorityQueue adalah struktur data Heap di Java. Dengan bantuan, kita boleh mencapai O (n * log k) penyelesaian . Lebih-lebih lagi, ini akan menjadi penyelesaian yang lebih pantas daripada yang sebelumnya. Oleh kerana masalah yang dinyatakan, k selalu kurang dari ukuran larik. Jadi, ini bermaksud bahawa O (n * log k) ≤ O (n * log n).

Algoritma berulang sekali melalui susunan yang diberikan . Pada setiap lelaran, kami akan menambahkan elemen baru ke timbunan. Selain itu, kita akan memastikan ukuran timbunannya kurang daripada atau sama dengan k . Oleh itu, kita mesti mengeluarkan elemen tambahan dari timbunan dan menambah yang baru. Akibatnya, setelah melakukan iterasi melalui array, timbunan akan mengandungi nilai k terbesar:

public List findTopK(List input, int k) { PriorityQueue maxHeap = new PriorityQueue(); input.forEach(number -> { maxHeap.add(number); if (maxHeap.size() > k) { maxHeap.poll(); } }); List topKList = new ArrayList(maxHeap); Collections.reverse(topKList); return topKList; }

4. Algoritma Pemilihan

Terdapat banyak pendekatan untuk menyelesaikan masalah yang diberikan. Dan, walaupun berada di luar skop tutorial ini, menggunakan pendekatan algoritma Pemilihan akan menjadi yang terbaik kerana menghasilkan kerumitan waktu linear.

5. Kesimpulan

Dalam tutorial ini, kami telah menerangkan beberapa penyelesaian untuk mencari unsur k terbesar dalam sebuah array.

Seperti biasa, kod contoh boleh didapati di GitHub.