topK的問題,可以考慮用堆來維護,比如說這個題,維護一個大小爲k的最大堆(當然最大是自定義排序後的最大),那麼在堆中的元素就是從小到大的元素。因爲是大根堆,堆頂元素就是堆中的topK;
元素入堆時:
- 如果元素入堆時,加入元素比堆頂小,就更換堆頂元素;
- 否則無操作
通過維護一個堆(java中用優先隊列實現),那麼堆頂元素就是我們要的topK了。
優化:
另外就本題來說,每一個數的權值都是一定的,如果之前算過了,就直接從map中獲得
class Solution {
public int getKth(int lo, int hi, int k) {
//大根堆
PriorityQueue<int[]> pq = new PriorityQueue<>((o1,o2)-> {
if(o1[1] == o2[1]) { //如果權重相同,按數字本身大小排序
return o2[0] - o1[0];
}
return o2[1] - o1[1];
});
HashMap<Integer, Integer> hs = new HashMap<>();
for (int i = lo; i <= hi; i++) {
int temp = i;
int count = 0;
while(temp != 1) {
if(hs.containsKey(temp)) { //如果算過,用緩存中的權值
count = hs.get(temp) + count;
break;
}else {
if(temp%2 == 0) {
temp >>= 1;
}else {
temp = 3*temp +1;
}
count++;
}
}
if(!hs.containsKey(i)) { //算完了,就放入緩存
hs.put(i, count);
}
int[] arr = new int[2];
arr[0] = i;
arr[1] = count;
if(pq.size() < k) { //維護一個大小爲k的最大堆
pq.offer(arr);
}else {
int[] top = pq.peek();
if(arr[1] < top[1] || (arr[1] == top[1] && arr[0] < top[0])) {
pq.poll();
pq.offer(arr);
}
}
}
return pq.poll()[0];
}
}