蓝桥杯-日志统计(Java)

标题:日志统计

小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有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

扫描二维码关注公众号,回复: 5626046 查看本文章

100 3

【输出样例】

1

作者:Pysrain
来源:CSDN
原文:https://blog.csdn.net/qq_39020387/article/details/79905912
版权声明:本文为博主原创文章,转载请附上博文链接!

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;
	}
 
}

以下是自己写的代码:

import java.util.*;

public class Main{
	public static int maxn = (int)1e6+10;
	public static int[]ans = new int[maxn];
	public static int n,d,k,ts,id,count,l,r,sum,cnt;
	
	public static void main(String[] args){
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		d = scanner.nextInt();
		k = scanner.nextInt();
		Map<Integer,Integer> map = new TreeMap<>(
				new Comparator<Integer>(){
					public int compare(Integer o1,Integer o2){
						if(o1.equals(o2)){
							return 1;
						}
						else{
							return o1-o2;
						}
					}
				}
				);
		for(int i=0;i<n;i++){
			ts = scanner.nextInt();
			id = scanner.nextInt();
			map.put(id,ts);
		}
		for(int i=1;i<=maxn;i++){
			if(judge(i,map)){
				ans[++cnt]=i;
			}
		}
		//Arrays.sort(ans+1,ans+1+cnt);
		for(int i=1;i<=cnt;i++){
			System.out.println(ans[i]);
		}
	}
	public static boolean judge(int i,Map<Integer,Integer>map){
		count = 0;
		List<Integer> list = new ArrayList<>();
		for(Map.Entry<Integer,Integer> entry : map.entrySet()){
			if(entry.getKey()==i){
				count++;
				list.add(entry.getValue());
			}
		}
		if(count<k){
			return false;
		}
		Collections.sort(list);
		l=0;
		r=0;
		sum=0;
		while(l<=r&&r<=list.size()-1){
			sum++;
			if(sum>=k){
				if(list.get(r)-list.get(l)<=d-1){
					return true;
				}else{
					l++;
					sum--;
				}
			}
			r++;
		}
		return false;
	}
}

笔记:
1.写了这道题,java的ArrayList,Collecitons,TreeMap,Comparator都练的差不多了。嗯,题目导向型学习集合知识。
2.下次定义maxn就用

public static int maxn = (int)1e6+10;
public static int[] a =new int[maxn];
//数组就直接用maxn定义

3.Map和List集合框架不能在静态区域定义,不然不能在函数动态区域里赋值,所以要在main里或者函数里地定义集合,如果main里定义的还必须得作为参数传到调用的方法里才行。
4.对象判断相等o1.equals(o2)
5.object类型可以作为任意类定义
6.如果java需要用vector存邻接表形式的键值对,就使用TreeMap修改compare方法改为可存相同key,存好后再用分别把每一个相同key的value通过map.entrySet()取出来并放到list里进行sort,同时记录相同key的个数,个数为0,说明没有这个key。最后和vector的邻接表效果一样,同样是对所有不同的key的分别对应的value进行排序。

猜你喜欢

转载自blog.csdn.net/w1304636468/article/details/88623813