原题链接:(28条消息) 星期一-蓝桥杯-基础-CSDN算法技能树
日志统计
题目
题目描述
小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N 行。
其中每一行的格式是:
ts id
表示在 ts 时刻编号 id 的帖子收到一个”赞”。
现在小明想统计有哪些帖子曾经是”热帖”。
如果一个帖子曾在任意一个长度为 D 的时间段内收到不少于 K 个赞,小明就认为这个帖子曾是”热帖”。
具体来说,如果存在某个时刻 T 满足该帖在 [T,T+D) 这段时间内(注意是左闭右开区间)收到不少于 K 个赞,该帖就曾是”热帖”。
给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。
输入格式
第一行包含三个整数 N,D,K。
以下 N 行每行一条日志,包含两个整数 ts 和 id。
输出格式
按从小到大的顺序输出热帖 id。
每个 id 占一行。
数据范围
1≤K≤N≤10E5,
0≤ts,id≤10E5,
1≤D≤10000
输入样例:
71020101010101019110031003
输出样例:
13
问题分析
本体设计的数据是成对出现,需要成对进行处理,
根据特性我们考虑使用类似字典方法,注意HsshSet方法不可以录入重复数据,
所以使用HashMap
考虑问题的对比方法,是对比d时间内,对点赞数量进行比较,
利用尺取发可以实现一种比较高效的暴力列举
尺取法 就是按照固定间距取两个端点的数据,特殊的列举方法
代码实现
package 刷题;
import java.util.HashMap;
import java.util.Scanner;
public class 日志统计 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//日志n行
int n = sc.nextInt();
//单位时间
int d = sc.nextInt();
//热帖判定值n
int k = sc.nextInt();
//字典1键值为id&&ts:字典2键值即点赞量
HashMap<Integer, Integer> map1 = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> map2 = new HashMap<Integer, Integer>();
//n行日志循环处理,获取ts,id数据
for (int i = 0; i < n; i++) {
int ts = sc.nextInt();
int id = sc.nextInt();
//分类处理,
//未曾记录的id
if (map1.get(id) == null) {
//存储id和ts
map1.put(id, ts);
//记录首次点赞帖子
map2.put(id, 1);
//已经含有的id、
} else {
if (map1.get(id) == id || (map1.get(id) + d) > ts) {
map2.put(id, map2.get(id) + 1);
}
}
}
//全部的赞和id已经录入
//获取键值,判断后输出即可
for (int key : map2.keySet()) {
if (map2.get(key) >= k) {
System.out.println(key);
}
}
sc.close();
}
}
使用样例输入检测
星期一
题目
整个20世纪(1901年1月1日至2000年12月31日之间),一共有多少个星期一?(不要告诉我你不知道今天是星期几)
问题分析
包含整个世纪也就是正一百年,所以对于天数只考虑闰年
对于星期,我们使用 Calendar类可以获得,
对于 英美格式的日历来说 星期日是一个周的开始,
对于 中国格式来说周一是开始,
这里我使用英美格式,,,(理智爱国,只是初高中都是周日开学,习惯了)
这个函数应该是出现了问题,,根据查日历和讨论区的情况来看,
即2000.12.31是星期日。
即1901.01.01是星期二,这个日历查不到了,不过很容易明白确实是周二
方法是对所有整周计数,所以就算从任意星期几开始,我们取的整周都是有且仅有一个星期一的,
所以我们只考虑余下的,是否包含周一,有就加1,没有就是原结果
经过博主(30条消息) baijjdvin的博客_CSDN博客-Java复习,2023蓝桥杯记录领域博主提醒改进
代码实现
package 刷题;
import java.util.Calendar;
public class 星期一 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Calendar start = Calendar.getInstance();
start.set(1901, 1, 1);
System.out.println("start星期"+start.get(Calendar.DAY_OF_WEEK));//判断起始日期是星期几
Calendar end = Calendar.getInstance();
end.set(2000, 12, 31);
System.out.println("end是星期"+end.get(Calendar.DAY_OF_WEEK));//判断起始日期是星期几
//是整年,涵盖全世纪100年所以直接计算就行
int year = 1901;
//统计天数计算几个周
int sum = 0;
while(year<=2000) {
if(year%4==0&&year%100!=0||year%400==0) {
sum+=366;
}else {
sum+=365;
}
year++;
}
System.out.println(sum/7);//5217
}
}
输出结果即5217,
猜年龄
题目
美国数学家维纳(N.Wiener)智力早熟,11岁就上了大学。他曾在1935~1936年应邀来中国清华大学讲学。
一次,他参加某个重要会议,年轻的脸孔引人注目。于是有人询问他的年龄,他回答说:“我年龄的立方是个4位数。我年龄的4次方是个6位数。这10个数字正好包含了从0到9这10个数字,每个都恰好出现1次。”
请你推算一下,他当时到底有多年轻。
问题分析
包含10个不同数字可以使用set集合的不可以包含重复数据的特性
将3次方和4次方的结果以字符串的类型录入
代码实现
package 刷题;
import java.util.HashSet;
import java.util.Set;
public class 猜年龄 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//循环的范围给大一点就可以,
for (int age =0; age <=200 ; age++) {
String age3= age*age*age+"";
/*字符串类型,直接输出的话就是int了
所以加一个无意义来保证是字符串类型*/
String age4= age*age*age*age+"";
//满足三个条件就输出
if(age3.length()==4&&age4.length()==6&&CheckAge(age3,age4)){
System.out.println(age);
break;
}
}
}
public static boolean CheckAge(String age3,String age4){
//l利用set集合不可以包含相同数的特性,
String str = age3+age4;
Set<Character> set =new HashSet<Character>();
for (int i = 0; i <str.length() ; i++) {
set.add(str.charAt(i));
}
//当包含全部数字,也急速长度为10就返回
return set.size()==10 ;
}
}
输出结果,正确答案 18