第九届蓝桥杯省赛--日志统计

版权声明:本文为博主原创文章,未经博主允许不得转载。

一、问题描述

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

  资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗  < 1000ms

  请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。不要使用package语句。不要使用jdk1.7及以上版本的特性。主类的名字必须是:Main,否则按无效代码处理。

二、题目类型:编程大题、排序、尺取法

三、解题思路及代码

  这道题人眼看着觉得挺容易,但是怎么用程序准确表达出来呢?我想了很久,不太会。。。最后试着用暴力破解。。。我甚至还单独写了一个Blog类(微笑.jpg)

 1 import java.util.HashSet;
 2 import java.util.Scanner;
 3 import java.util.Set;
 4 
 5 public class LogStatistics {
 6 
 7     public static void main(String[] args) {
 8 
 9         Scanner input = new Scanner(System.in);
10         int n = input.nextInt();
11         int d = input.nextInt();// 以秒为单位
12         int k = input.nextInt();
13         Blog[] arr = new Blog[n];
14         for (int i = 0; i < arr.length; i++) {
15             arr[i] = new Blog();
16             arr[i].setTime(input.nextInt());
17             arr[i].setId(input.nextInt());
18         }
19 
20         Set<Integer> set = new HashSet<>();// 无序、不重复
21         for (int i = 0; i < arr.length; i++) {//遍历每一行数据
22             int count = 1;
23             for (int j = i + 1; j < arr.length; j++) {
24                 if (arr[i].id == arr[j].id && arr[j].time - arr[i].time < d) {
25                     count++;
26                 }
27             }
28             if (count >= k) {
29                 set.add(arr[i].id);
30             }
31         }
32         System.out.println(set.toString());
33 
34     }
35 }
36 
37 class Blog {
38     int time;
39     int id;
40 
41     public void setTime(int seconds) {
42         this.time = seconds;
43     }
44 
45     public void setId(int id) {
46         this.id = id;
47     }
48 
49     public String toString() {
50         return time + " " + id;
51     }
52 }

  以上代码在数据量小的时候还勉强可以通过,一旦数据大了肯定会超时。。。所以我重新写,还用到了一些框架。

 1 import java.util.ArrayList;
 2 import java.util.Collections;
 3 import java.util.Comparator;
 4 import java.util.HashSet;
 5 import java.util.Iterator;
 6 import java.util.List;
 7 import java.util.Scanner;
 8 import java.util.Set;
 9 import java.util.TreeSet;
10 
11 public class LogStatistics {
12 
13     public static void main(String[] args) {
14         Scanner input = new Scanner(System.in);
15         int n = input.nextInt();//有n条日志
16         int d = input.nextInt();// 以秒为单位
17         int k = input.nextInt();//热帖标准
18         int[][] arr = new int[n][2];//用二维数组存储数据
19         for (int i = 0; i < n; i++) {
20             for (int j = 0; j < 2; j++) {
21                 arr[i][j] = input.nextInt();
22             }
23         }
24         Set<Integer> set = new HashSet<>();//给id分类,HashSet 无序、不重复
25         for (int i = 0; i < n; i++) {
26             set.add(arr[i][1]);
27         }
28         Set<Integer> treeset = new TreeSet<>();//存热帖id,TreeSet 自动排序、不重复
29         Iterator<Integer> iter = set.iterator();//遍历每个id
30         while (iter.hasNext()) {
31             int id = iter.next();
32             int count = 1;//记录点赞次数,每次初始化为1,因为一个id本身就是一次点赞
33             List<Integer> time = new ArrayList<>();//存当前id收到点赞的时间
34             for (int i = 0; i < n; i++) {//遍历所有的数据,找到与当前id相等的值,并存储时间
35                 if (arr[i][1] == id) {
36                     time.add(arr[i][0]);
37                 }
38             }
39             Collections.sort(time);//将时间按升序排序
40             System.out.println(time.toString()); //我用来测试时间输出正确与否
41             for (int i = 0; i < time.size() - 1; i++) {//遍历时间链表
42                 for(int j=i+1; j< time.size(); j++) {// 遍历第 i 个以后的每个时间元素
43                     if(Math.abs(time.get(i) - time.get(j)) < d) {//如果它们的差 < 给定的时间段
44                         count++;//“合法”点赞次数自增 1
45                     } else {
46                         break;//否则此时间段里达不成热帖或者已经达成热帖
47                     }
48                 }
49                 if (count >= k) {//如果达成热帖,就把该 id 加入treeset
50                     treeset.add(id);
51                     break;
52                 }
53                 //达不成热帖,进入下一次循环,探寻下一个时间段里是否可以成为热帖
54             }
55         }
56         Iterator<Integer> result = treeset.iterator();
57         while(result.hasNext()) {
58             System.out.println(result.next());
59         }
60     }
61 }

  但是吧。。。我觉得没有优化到哪里去。。。。尺取法我还不会。。。(哭.jpg)

 

猜你喜欢

转载自www.cnblogs.com/crush-u-1214/p/10502357.html