Top K Element algoritmaları bana en uzun, en kısa en X ölçütüne uyan ilk K elemanı ver anlamına gelir. Algoritma kabaca şöyle. Yani önce elemanları bir ölçüte göre sayıyoruz ve daha sonra bunları bir minheap veri yapısına ekleyip, Top K elemanı buluyoruz.
1. We first go through the array and count each element’s frequency, creating a distribution map.2. We then go through the key-value pairs in the distribution map, and maintain a min-heap of size k based on frequency.
Dağıtık (Distributed) Top K
Burada MapReduce kullanmak gerekiyor. Bu algoritmanın biraz daha gelişmiş hali "Top K Frequent Elements in a Time Window"
Top K Değerini Bilmiyorsak
Eğer en uzun elemanların tamamını ver deseydi, Top K eleman algoritmaları kullanılamaz çünkü, ölçütü sağlayan kaç tane nesne olduğunu bilmiyoruz.
Top K Elements Çözümleri
Bu algoritmaların bir çok çözümü var
Örnek - Listeyi Dolaşarak PriorityQueue İle Sıralamak
En uzun 2 string'i bulmak isteyelim. Şöyle yaparız.
int topK = 2;PriorityQueue<String> pq = new PriorityQueue<>(String::length);for (String word : wordList){pq.offer(word);if (pq.size() > topK){pq.poll(); //En kısayı sil}}while (!pq.isEmpty()){pq.remove();}
Örnek - Tree'yi Dolaşarak PriorityQueue İle Sıralamak
Şöyle yaparız
public List<Integer> closestKValues(TreeNode root, double target, int k) {// 1. Create a Priority Queue, sorted on diffsPriorityQueue<double[]> pq = new PriorityQueue<double[]>(
Comparator.comparing(a -> a[1]));Stack<TreeNode> stack = new Stack<>();stack.push(root);// 2. Traverse tree iteratively and place items in PQwhile (!stack.isEmpty()) {TreeNode current = stack.pop();pq.add(new double[] {current.val /* value */,
Math.abs(current.val - target /* diff */ )});if (current.left != null) {stack.push(current.left);}if (current.right != null) {stack.push(current.right);}}// 3. Prepare the output with needed K-values.List<Integer> result = new ArrayList<>();for (int i = 0; i < k; ++i) {if (!pq.isEmpty()) {result.add((int) pq.poll()[0]);}}return result;}
Örnek - Girdi Olan Dizi Sıralı Olmalı
En yüksek frekans (frequency) değerine sahip K elementi bulmak isteyelim. Dizi sıralı olduğu için şöyle yaparız. process() metodu her değerden kaç tane olduğunu bulur ve addOrReplace() metodunu çağırır. countMap içinde Top K Elements sırasız biçimde bulunur
class TopN {
private final int maxSize;
private Map<Long, Long> countMap;
public TopN(int maxSize) {
this.maxSize = maxSize;
this.countMap = new HashMap(maxSize);
}
private void addOrReplace(long value, long count) {
if (countMap.size() < maxSize) {
countMap.put(value, count);
} else { //Top K sınırına geldik
Optional<Entry<Long, Long>> opt = countMap.entrySet().stream()
.min(Entry.comparingByValue()); //En küçük frekansa sahip elemanı bul
Entry<Long, Long> minEntry = opt.get();
if (minEntry.getValue() < count) { //Eğer mevcut frekans daha küçükse, sil
countMap.remove(minEntry.getKey());
countMap.put(value, count);
}
}
}
public void process(long[] data) {
long value = data[0];
long count = 0;
for (long current : data) {
if (current == value) {
++count;
} else {
addOrReplace(value, count);
value = current;
count = 1;
}
}
addOrReplace(value, count);
}
}
Hiç yorum yok:
Yorum Gönder