目录
[题目链接:1.日期统计 - 蓝桥云课 (lanqiao.cn)](#题目链接:1.日期统计 - 蓝桥云课 (lanqiao.cn))
题目链接:1.日期统计 - 蓝桥云课 (lanqiao.cn)
题目描述
小蓝现在有一个长度为 100 的数组,数组中的每个元素的值都在 0到9的范围之内。数组中的元素从左至右如下所示
5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1 0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
现在他想要从这个数组中寻找一些满足以下条件的子序列:
1.子序列的长度为 8
2.这个子序列可以按照下标顺序组成一个yyyymmdd 格式的日期,并且要求这个日期是 2023 年中的某一天的日期,例如20230902,20231223。yyyy表示年份,mm 表示月份,dd 表示天数,当月份或者天数的长度只有一位时需要一个前导零补充。
请你帮小蓝计算下按上述条件一共能找到多少个不同的 2023 年的日期。对于相同的日期你只需要统计一次即可。
思路
这题就是一个老六题!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我一开始以为是要找一个连续的子序列,md然后一直过不了,甚至跑出来的答案是0,wdf!!!玩神魔,结果我又读了好几遍题目,这也没说是连续的子序列啊,于是我的代码就没有去找连续的子数列,好家伙,终于拿下了,服了,废了,倦了。
代码思路
定义数据结构:
mday
数组存储了不同月份的天数,其中二月份由于是2023非闰年,所以是28天。num100
数组包含一组100个整数,用于与日期的每一位进行比对。nowTime
数组初始值为20230000
,用于表示日期序列,格式为YYYYMMDD
。
处理每一个月:
- 通过两重循环遍历一年中的每一天。外层循环代表月份
i
,内层循环代表对应月份的天数j
。 - 为了构造当前日期,
nowTime
数组需要根据循环变量i
和j
更新代表月和日的部分。 - 月份的十位和个位分别由
i / 10
和i % 10
给出,存储到nowTime[4]
和nowTime[5]
中。 - 日期的十位和个位由
j / 10
和j % 10
给出,存储到nowTime[6]
和nowTime[7]
中。
检查日期序列在num100
中是否存在:
- 对于每个
nowTime
所表示的日期,调用checkHave
函数来检查这个日期序列是否在num100
数组中以非连续形式出现。 checkHave
函数通过两个指针p100
和pnow
分别在num100
和nowTime
上移动。- 如果两个指针所指元素相同,则两个指针都往前移动;如果不同,那么只移动
num100
的指针。 - 如果
pnow
达到8,说明nowTime
的所有数字都在num100
中顺序出现过了,这时函数返回1。 - 否则,如果在
num100
遍历完毕还未找到匹配,返回0。
计数匹配的日期数:
- 主循环里面会累加
checkHave
函数的返回值到变量res
中。 - 每次成功匹配(找到
nowTime
中的日期序列在num100
中以非连续形式存在),计数器res
增加1。
输出结果:
- 最后,输出的
res
变量表示在一年中发现的符合条件的日期数。
代码实现
java
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
// 存储不同月份的天数
int[] mday = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int[] num100 = { 5, 6, 8, 6, 9, 1, 6, 1, 2, 4, 9, 1, 9, 8, 2, 3, 6, 4, 7, 7, 5, 9, 5, 0, 3, 8, 7, 5, 8, 1, 5, 8, 6,
1, 8, 3, 0, 3, 7, 9, 2, 7, 0, 5, 8, 8, 5, 7, 0, 9, 9, 1, 9, 4, 4, 6, 8, 6, 3, 3, 8, 5, 1, 6, 3, 4, 6, 7,
0, 7, 8, 2, 7, 6, 8, 9, 5, 6, 5, 6, 1, 4, 0, 1, 0, 0, 9, 4, 8, 0, 9, 1, 2, 8, 5, 0, 2, 5, 3, 3 };
// 初始数据
int[] nowTime = { 2, 0, 2, 3, 0, 0, 0, 0 };
// res
int res = 0;
for (int i = 1; i <= 12; i++) {
// 获得月份
// 如果是十月之后,那么格式就是1x的格式
nowTime[4] = i / 10;
// 取模得最后一位
nowTime[5] = i % 10;
// 获得天数
for (int j = 1; j <= mday[i]; j++) {
// 取左边的数
nowTime[6] = j / 10;
// 取右边的数
nowTime[7] = j % 10;
res += checkHave(num100, nowTime);
}
}
System.out.println(res);
}
public static int checkHave(int[] num100, int[] nowTime) {
// 定义出,两个指针,分别判断100个数和当前的序列样子
int p100 = 0;
int pnow = 0;
while (p100 < 100 && pnow < 8) {
if (num100[p100] == nowTime[pnow]) {
// 如果当前位置对上了
p100++;
pnow++;
}else {
// 没对上
p100++;
}
}
return pnow == 8 ? 1 : 0;
}
}
这里的checkHave
函数实际上是在检查nowTime
数组中的数字序列是否在另一个较长的num100
数组中以任意顺序出现(不必连续)。这意味着只要nowTime
数组的所有元素都在num100
数组中按顺序出现(不必相邻),就会返回1,表明匹配成功;否则,返回0表示没有找到匹配的序列。
checkHave
函数逐个比较nowTime
数组中的数字,与num100
数组中的数字进行匹配。只要找到匹配的数字,就同时将两个数组的指针向前移动,依次检查nowTime
数组中的下一个数字。如果num100
中的数字与nowTime
当前位置的数字不匹配,则只移动num100
的指针,继续搜索下一个可能匹配的数字。当nowTime
数组中的所有元素都成功匹配时,即pnow
达到数组的长度时,函数返回1;如果num100
数组已遍历完成但未找到完全匹配的序列,则返回0。
整个主程序的逻辑是生成一个日期序列,并检查这个序列在num100
数组中以任意顺序是否出现过。如果出现过,则计数加一。最后输出这个计数,表示在一年的日期中有多少个是在num100
中可以找到匹配的序列的。
总结
我真的服啦,这老六题目真的有时候能不能描述™清楚一点啊,我*****