关键词:日期,集合。
思路分析(最重要!)
存储
题目里面给到“可能有重复日期”实际上是一种提示——我们可以考虑使用集合来解决这个问题。哈希集合 的平均查找时间复杂度是 $O(1)$ 我们可以快速的判断一个日期是否存在于集合中。
所以,我们将日期都存进一个哈希集合。
遍历
我们使用 foreach 可以方便地遍历哈希集合的对象。设想现在我们取出了一个日期对象,要怎么判断它是否是连续的?对!就是看它的前一天或者后一天在不在集合里。
我们规定,判断前一天是否存在。如果前一天不存在,那么这一天就是连续打卡的起始日期。那么,我们只需要循环判断,直到不连续,就可以计算出连续的天数,并且判断其是否为最大连续天数。
伪代码:
for 每个 date in checkDates:
if 集合不包含 date 的前一天:
currentDays = 0
nowDay = date
while 集合包含 nowDay:
currentDays += 1
nowDay = nowDay.plusDays(1)
ans = max(ans, currentDays)
前置知识
1. HashSet
- 作用:存储不重复的元素,适合本题去重。
- 常用方法:
add(x):添加元素。contains(x):判断元素是否存在。
- 时间复杂度:查找和插入的平均时间复杂度为 $O(1)$。
2. LocalDate
java.time.LocalDate 是 Java 8 引入的日期类,只表示年月日,不包含时间和时区。它是不可变对象,日期运算会返回新的对象。
本题常用方法:
| 方法 | 作用 |
|---|---|
LocalDate.parse(text) | 将 yyyy-MM-dd 格式的字符串转换为日期 |
date.plusDays(1) | 获取后一天,自动处理跨月、跨年和闰年 |
date.minusDays(1) | 获取前一天 |
例如:
LocalDate date = LocalDate.parse("2026-01-01");
LocalDate nextDay = date.plusDays(1); // 2026-01-02
注意:plusDays() 和 minusDays() 不会修改原日期,需要使用返回值。
完整题解
Scanner使用方便,但在大规模输入时通常比BufferedReader慢。对于竞赛中的大量输入,可以根据数据规模选择更高效的读取方式。所以在做竞赛题目时建议使用BufferedReader+StringTokenizer的组合。本题读入都是以行为单位,所以可以不使用StringTokenizer。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDate;
import java.util.HashSet;
public class Main {
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static LocalDate nextDate() throws IOException {
return LocalDate.parse(br.readLine());
}
public static void main(String[] args) throws IOException{
int n = Integer.parseInt(br.readLine());
HashSet<LocalDate> checkDates = new HashSet<>();
for (int i = 0; i < n; i++) {
checkDates.add(nextDate());
}
int ans = 0;
for (LocalDate date : checkDates) {
LocalDate nowDay = date;
int currentDays = 0;
if (!checkDates.contains(nowDay.minusDays(1))) {
currentDays = 0;
do {
currentDays += 1;
nowDay = nowDay.plusDays(1);
} while (checkDates.contains(nowDay));
ans = Math.max(ans, currentDays);
}
}
System.out.println(ans);
}
}
复杂度总结
时间复杂度: 设去重后的日期数量为 $m$ ,外层遍历需要 $O(m)$ 次。由于每个连续区间只会从起点开始扫描一次,每个日期最多参与一次区间扫描,因此在 HashSet 操作具有平均常数时间的前提下,整体期望时间复杂度为 $O(n)$ 。
空间复杂度: 使用 HashSet 存储日期,需要 $O(n)$ 的额外空间。
3
回复