蓝桥杯——日志统计

标题:日志统计

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:

ts id

表示在ts时刻编号id的帖子收到一个"赞"。

现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。

具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。

给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。

【输入格式】
第一行包含三个整数N、D和K。 
以下N行每行一条日志,包含两个整数ts和id。

对于50%的数据,1 <= K <= N <= 1000 
对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000

【输出格式】
按从小到大的顺序输出热帖id。每个id一行。

【输入样例】
7 10 2 
0 1 
0 10 
10 10 
10 1 
9 1
100 3 

100 3

【输出样例】

1

3

import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;

public class 日志统计 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		int n=sc.nextInt();//帖子总数量
		int d=sc.nextInt();//区间长度
		int k=sc.nextInt();//不少于k个赞
		
		Map<Integer,Integer> m=new TreeMap<>(new Comparator<Integer>() {
			//重写compare方法,使Treemap可以放入相同健值的条目
			@Override
			public int compare(Integer o1, Integer o2) {
				if(o1.equals(o2)){
					return 1;//return 0;
				}else {
					return o1-o2;
				}
			}
			
		});
		for (int i = 1; i <= n; i++) {
			int ts=sc.nextInt();
			int id=sc.nextInt();
			m.put(id,ts);
		}
		int x[]=new int[100001];//记录满足所有题干条件的id值
		int num=0;//id数量
		//遍历id
		for (int id = 1; id < x.length; id++) {
			if(check(m,id,d,k)){//是否满足
				x[++num]=id;
			}
		}
		//遍历输出结果
		for (int i = 1; i <= num; i++) {
			System.out.println(x[i]);
		}
	}
	/**
	 * 确定此id是否为满足题干条件的id
	 * @param m 存储
	 * @param i id
	 * @param d 区间长度
	 * @param k 最少的赞个数
	 * @return
	 */
	private static boolean check(Map<Integer, Integer> m, int i, int d, int k) {
		int count=0;//记录id出现的个数
		LinkedList<Integer> list=new LinkedList<>();
		for (Map.Entry<Integer, Integer> entry : m.entrySet()) {
			if(entry.getKey()==i){
				count++;
				list.add(entry.getValue());//将key值也就是id,添加的list中
			}
		}
		if(count<k){//id的个数小于要求的   最小赞的个数k
			return false;
		}
		Collections.sort(list);
		int st=0;//初始指针
		int en=0;//结束指针
		int sum=0;//当前赞的个数和
		while (st<=en && en<list.size()) {
			sum++;
			if(sum>=k){//如果当前的赞的个数 >=k,也就是不少于k个赞
				//判断时间区间是否符合在[T,T+d)之中
				if(list.get(en)-list.get(st) < d){
					return true;
				}else {//不符合
					st++;//初始指针右移
					sum--;//当前赞数减1
				}
			}
			//每次en指针都会右移,直到到达结尾
			en++;
			
		}
		//如果超出了while循环的条件仍然没有返回的值,那么此id就不是‘热帖’
		return false;
	}

}

猜你喜欢

转载自blog.csdn.net/qq_39020387/article/details/79905912