首页 > 试题广场 >

出现次数的TopK问题

[编程题]出现次数的TopK问题
  • 热度指数:1375 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定String类型的数组strArr,再给定整数k,请严格按照排名顺序打印 出次数前k名的字符串。
[要求]
如果strArr长度为N,时间复杂度请达到


输入描述:
第一行两个整数N, k。N表示数组大小
接下来N行,每行一个字符串


输出描述:
输出K行,每行有一个字符串和一个整数。
你需要按照出现出现次数由小到大输出,若出现次数相同时字符串字典序较小的优先输出
示例1

输入

4 2
1
2
3
4

输出

1 1
2 1
示例2

输入

4 2
1
1
2
3

输出

1 2
2 1

备注:


保证输入的字符串仅含有大小写字母/数字
先计数,然后用优先队列获得topk
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.*;

class Pair {
    String key;
    int value;
    public Pair(String key, int value) {
        this.key = key;
        this.value = value;
    }
}

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] params = br.readLine().split(" ");
        int n = Integer.parseInt(params[0]);
        int k = Integer.parseInt(params[1]);
        HashMap<String, Integer> counter = new HashMap<>();
        for(int i = 0; i < n; i++){
            String key = br.readLine();
            counter.put(key, counter.getOrDefault(key, 0) + 1);
        }
        PriorityQueue<Pair> pq = new PriorityQueue<>(new Comparator<Pair>(){
            @Override
            public int compare(Pair pair1, Pair pair2) {
                if(pair1.value != pair2.value)
                    return pair2.value - pair1.value;
                else
                    return pair1.key.compareTo(pair2.key);
            }
        });
        for(String key: counter.keySet())
            pq.offer(new Pair(key, counter.get(key)));
        for(int i = 0; i < k; i++){
            Pair pair = pq.poll();
            System.out.println(pair.key + " " + pair.value);
        }
    }
}

发表于 2021-10-20 15:52:06 回复(0)
#include <bits/stdc++.h>
using namespace std;

struct P{
    string s;
    int cnt;
    P(string s, int cnt):s(s),cnt(cnt){}
    bool operator<(P p)const{
        if(cnt == p.cnt)
            return s > p.s;
        return cnt < p.cnt;
    }
};

int main(){
    string s;
    int n, k;
    cin>>n>>k;
    unordered_map<string, int> mp;
    for(int i=0;i<n;i++){
        cin>>s;
        mp[s]++;
    }
    priority_queue<P> q;
    for(auto &p: mp)
        q.push(P{p.first, p.second});
    while(k--){
        cout<<q.top().s<<" "<<q.top().cnt<<endl;
        q.pop();
    }
    return 0;
}

发表于 2020-04-10 05:47:45 回复(2)
经典TopK问题,维护一个大小为k的堆即可:
using namespace std;
map<string,int> mp;
class cmp
{
    public:
    bool operator()(string s1,string s2)
    {
        if(mp[s1]<mp[s2])
            return false;
        else if(mp[s1]>mp[s2])
            return true;
        else
        {
            return s1<s2;//否则按照字典序排列
        }
    }
};
int main()
{
    int n,k;
    cin>>n>>k;
    string s;
    for(int i=0;i<n;i++)
    {
        cin>>s;
        mp[s]++;
    }
    priority_queue<string,vector<string>,cmp> q;  //小根堆
    for(auto i:mp)
    {
        if(q.size()<k)
            q.push(i.first); //当还不够k个时
        else
        {
            if(i.second>mp[q.top()])  //如果新来的数出现次数更多  那么替换出堆顶
            {
                q.pop();
                q.push(i.first);
            }  
        }
    }
    
    vector<string> ans1;
    vector<int> ans2;
    while(q.empty()==false)
    {
        ans1.push_back(q.top());
        ans2.push_back(mp[q.top()]);
        q.pop();
        
    }
    for(int i=ans1.size()-1;i>=0;i--)
        cout<<ans1[i]<<" "<<ans2[i]<<endl;   
}


发表于 2020-12-04 00:43:37 回复(0)
#include<iostream>
(720)#include<cstdio>
#include<queue>
(789)#include<map>
using namespace std;
struct node{
    string s;
    int count;
    node(string ss,int ccount):s(ss),count(ccount){}
    bool operator<(const node &t)const{
        if(count!=t.count)
        {
            return count<t.count;
        }else{
            return s>t.s;
        }   
    }
};
int main(){
    int N,k;
    string s;
    map<string,int> m;
    scanf("%d %d",&N,&k);
    for(int i=0;i<N;++i){
       cin>>s;
       m[s]++;
    }
    priority_queue<node> q;
    map<string,int>::iterator it;
    for(it=m.begin();it!=m.end();++it){
        q.push(node(it->first,it->second));
    }
    while(!q.empty()&&k!=0){
        cout<<q.top().s<<" "<<q.top().count<<endl;
        q.pop();
        k--;
    }
    return 0;
}

发表于 2020-03-25 14:54:35 回复(0)
#include <bits/stdc++.h>
using namespace std;

struct Node{
    string str;
    int times;
    Node(string s, int t){
        str = s;
        times = t;
    }
    bool operator<(const Node& t)const{
        if(times != t.times){
            return times < t.times;
        }else{
            return str > t.str;
        }
    }
};
int main(){
    int n, k; cin >> n >> k;
    unordered_map<string, int> rmap;
    string s;
    for(int i=0; i<n; i++){
        cin >> s;
        if(rmap.count(s) != 0) rmap[s]++;
        else rmap[s] = 1;
    }
    priority_queue<Node> maxHeap;
    for(auto node : rmap){
        maxHeap.push(Node(node.first, node.second));
    }
    for(int i=0; i<k; i++){
        Node head = maxHeap.top(); maxHeap.pop();
        cout << head.str << " " << head.times << endl;
    }
    return 0;
}

发表于 2020-02-21 22:04:16 回复(0)

hashmap+小顶堆

from collections import defaultdict
import heapq
class node:
    def __init__(self,val,index):
        self.val = val
        self.index = index
    def __lt__(self, other):
        if self.val == other.val:
            return self.index > other.index
        else:
            return self.val < other.val

n, k = map(int, input().split())
l = []
for i in range(n):
    l.append(input())
d = defaultdict(int)
for e in l:
    d[e] += 1

pq = []
for kk,v in d.items():
    heapq.heappush(pq, node(v,kk))
    if len(pq) > k:
        heapq.heappop(pq)
res = []
while len(pq) > 0:
    t = heapq.heappop(pq)
    res.insert(0,[t.val,t.index])
for e in res:
    print(e[1],e[0])


发表于 2019-08-19 14:41:09 回复(0)