字符串出现次数的TopK问题
描述
给定一个字符串数组,再给定整数k,请返回出现次数前k名的字符串和对应的次数。
返回的答案应该按字符串出现频率由高到低排序。如果不同的字符串有相同出现频率,按字典序排序。
对于两个字符串,大小关系取决于两个字符串从左到右第一个不同字符的 ASCII 值的大小关系。
比如"ah1x"小于"ahb",“231”<”32“
字符仅包含数字和字母
解题
Solution1
/**
* Map集合 列表排序
*/
import java.util.*;
public class Solution {
public String[][] topKstrings(String[] strings, int k){
if (strings==null||strings[0].length()==0||k==0) return null;
String [][] res = new String[k][2];
TreeMap<String,Integer> tmp = new TreeMap<>();//排序顺序存储键/值对
for (int i = 0;i<strings.length;i++){
String s= strings[i];
if (!tmp.containsKey(s)){
tmp.put(s,1);
}else {
tmp.put(s,tmp.get(s)+1);
}
}
ArrayList<Map.Entry<String,Integer>> list = new ArrayList<>(tmp.entrySet());//存储键与键值的映射关系表
Collections.sort(list,((o1, o2) -> (o1.getValue().compareTo(o2.getValue()))==0? o1.getKey().compareTo(o2.getKey()):o2.getValue().compareTo(o1.getValue())));
//排序
for (int i = 0; i < k; i++) {
res[i][0] = list.get(i).getKey();
res[i][1] = String.valueOf(list.get(i).getValue());
}
return res;
}
}
Solution2
/**
* 大顶堆
*/
import java.util.*;
public class Solution2 {
public String[][] topKstrings (String[] strings, int k) {
// write code here
if (strings==null||strings[0].length()==0||k==0) return null;
String[][] result = new String[k][2];
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);
}
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;
}
public int compareTo(Node node) {
if(this.cnt != node.cnt) {
return this.cnt - node.cnt;
} else {
return -this.val.compareTo(node.val);
}
}
}
}