TopN问题堆排序求解
出现次数的TopK问题
http://www.nowcoder.com/questionTerminal/fd711bdfa0e840b381d7e1b82183b3ee
- 统计各个字符出现次数,使用Map
- 创建初始堆(大顶堆),定义出现次数大的字符串较大,出现次数相同是自然序较前的串较大
- 依次去K个堆顶元素并调整堆
import java.util.*;
public class Solution {
/**
* return topK string
* @param strings string字符串一维数组 strings
* @param k int整型 the k
* @return string字符串二维数组
*/
public String[][] topKstrings (String[] strings, int k) {
if(null == strings || strings.length == 0) {
return new String[0][];
}
String[][] result = new String[k][];
// 统计各个字符串出现次数
Map<String,Integer> cntMap = new HashMap();
for(String s : strings) {
cntMap.put(s, cntMap.getOrDefault(s, 0)+1);
}
// 创建初始堆 大顶堆
Node[] heapArr = new Node[cntMap.size()+1];
int idx = 0;
for(Map.Entry<String,Integer> entry : cntMap.entrySet()) {
Node node = this.new Node(entry.getKey(), entry.getValue());
heapArr[++idx] = node;
}
// 调整初始堆
for(int i = idx/2; i > 0; --i) {
shift(heapArr, i, heapArr.length);
}
// 取前K个
int limit = heapArr.length-1;
for(int i = 1; i <= k && i <= limit; ++i) {
String[] r = new String[]{heapArr[1].val, String.valueOf(heapArr[1].cnt)};
result[i-1] = r;
Node temp = heapArr[1];
heapArr[1] = heapArr[limit];
heapArr[limit] = temp;
--limit;
// 调整堆
shift(heapArr, 1, limit+1);
}
return result;
}
// 堆调整方法
private void shift(Node[] heapArr, int startIdx, int endIdx) {
int childIdx = 2 * startIdx;
if(childIdx+1 < endIdx && heapArr[childIdx+1].compareTo(heapArr[childIdx]) > 0) {
childIdx = childIdx + 1;
}
if(childIdx < endIdx && heapArr[childIdx].compareTo(heapArr[startIdx]) > 0) {
Node temp = heapArr[childIdx];
heapArr[childIdx] = heapArr[startIdx];
heapArr[startIdx] = temp;
shift(heapArr, childIdx, endIdx);
}
}
// 堆结点定义
class Node implements Comparable<Node> {
String val;
int cnt;
Node() {}
Node(String val, int cnt) {
this.val = val;
this.cnt = cnt;
}
//定义比较方法: cnt 大的大, cnt相同时,val自然序小的大
public int compareTo(Node node) {
if(this.cnt != node.cnt) {
return this.cnt - node.cnt;
} else {
return -this.val.compareTo(node.val);
}
}
}
} 

