大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
⭐️引言⭐️
大家好,我是执梗,蓝桥杯的报名快接近尾声,如果有兄弟还没报名不了解比赛,缺少视频讲解和真题资源的一定要阅读一下我的这篇蓝桥全解析——蓝桥全解析。为了帮助兄弟们更好准备比赛,我特意选取了蓝桥往年真题中许多能体现出蓝桥经典题型的题目——如暴力遍历、枚举、动态规划等等。其中最主要的还是枚举,枚举题目在蓝桥杯中是最热的考点且没有之一。可以说把枚举练好,就已经半只脚踏入了国赛的大门。有需要的兄弟们可以收藏一下,后续我会继续更新蓝桥真题题型专栏,和大家一起冲击蓝桥杯。下面的真题建议大家先自行思考后再看答案。原题视频资源在文章结尾。
?博客首页:执梗的博客
?欢迎关注?点赞?收藏⭐️留言?
❤️ :热爱Java学习,期待一起交流!
?作者水平很有限,如果发现错误,求告知,多谢!
?有问题可私信交流!!!
⭐️目录⭐️
?1.蓝桥刷题须知
蓝桥杯比赛并不像我们平时在力扣和牛客网刷题一样,对我们代码运行和时间有着限制。Java组采用的是eplipse编译器,C/C++才用的是DevC++。填空题我们需要在编译器中自己跑出答案,然后直接提交答案即可。所以大家不要担心什么啊这个代码难道不会超时吗,这个代码空间复杂度也太大了吧,人家只看你的答案是否正确,就算你把电脑跑烂了都没问题,所以要大胆尝试。
?2.经典例题讲解
?1.世纪末的星期(经典日期API问题)
题目:有邪教称1999年12月31日是世界末日,当然谣言已经不攻自破。还有人称今后的某个世纪末的12月31日,如果是星期一则会….有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!!!于是”谣言制造商”又修改为星期日…….
1999年12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即XX99年)的12月31日正好是星期天(即星期日)? 回答年份即可
public class 世纪末的星期 {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
for (int year = 1999; year <10000 ; year+=100) {
calendar.set(Calendar.YEAR,year);
calendar.set(Calendar.MONTH,11);//其实是12月
calendar.set(Calendar.DAY_OF_MONTH,31);
if (calendar.get(Calendar.DAY_OF_WEEK)==1) {
//sunday是第一天,所以为1时是Sunday,通过源码查看
System.out.println(year);// 2299
break;
}
}
}
}
?解析:之所以要讲这道经典例题,是因为日期问题是蓝桥杯的高频考点。Java组在这种题目占尽便宜,因为Java中有着Calendar这个日期API,这是非常重要的。它能几乎解决与日期相关的所有问题。这里我们通过设置年月份,然后判断是否是星期天,如果是则直接输出答案,非常简单。如果这题不使用CalendarAPI的话,还是非常麻烦的,所以Java组的小伙伴一定要学会。
?2.马虎的算式(五个for循环枚举问题)
题目:小明是个急性子,上小学的时候经常抄错题目。有一次老师出的36X495=?他却抄成了396X45?但结果却很戏剧性,他的答案是正确的!!因为36 * 495= 396 * 45=17280
类似这样的巧合可能还有很多,比如27 * 594=297 * 54。
假设a b c d e代表1~9不同的五个数字(注意是各不相同的数字,且不含0),能满足
这样的格式的式子总共有多少种?
public class 马虎的算式 {
public static void main(String[] args) {
int count=0;
for (int a = 1; a <= 9; a++) {
for (int b = 1; b <= 9; b++) { //每次for循环前要判断前面是否有相等元素
if (a != b) for (int c = 1; c <= 9; c++) {
if (b != c && a != c) for (int d = 1; d <= 9; d++) {
if (a != d && b != d && c != d) for (int e = 1; e <= 9; e++) {
if (a != e && b != e && c != e && d != e) {
if ((a * 10 + b) * (c * 100 + d * 10 + e) == (a * 100 + d * 10 + b) * (c * 10 + e)) {
count++;
}
}
}
}
}
}
}
System.out.println(count);//答案为142
}
}
?解析:这是道非常经典的枚举问题,很多人可能会觉得5个for循环这复杂度也太高了吧,但其实每个循环都是常数级,即使放到平时的刷题平台也不会超时。枚举类型的题目,需要大家答案的去实现,枚举当然就是想方设法去列出所有的情况,再判断是否符合题意。蓝桥杯对这种题型是钟爱有加,就是因为大家平时在各种刷题平台对这种题遇到比较少,一下紧张,不敢大胆地实现自己的思路。
?3.振兴中华(基础动规问题)
题目:小明参加了学校的趣味运动会,其中的一个项目是:跳格子
地上画着一些格子,每个格子里写一个字;如下图
从我做起振
我做起振兴
做起振兴中
起振兴中华
比赛时从左上角的的”从”字开始,只能横向或纵向跳到相邻的格子里,但不能跳到对角的格子,要求跳到”华”字结束。要求跳过的路线刚好是”从我做起振兴中华”这句话,请问小明有几种可能的跳跃路线
public class 振兴中华 {
public static void main(String[] args) {
int[][] arr=new int[4][5];//注意是四列五纵
for (int i = 0; i < 5; i++) {
arr[0][i]=1;
}
for (int i = 0; i < 4; i++) {
arr[i][0]=1;
}
for (int i = 1; i < 4; i++) {
for (int j = 1; j < 5; j++) {
arr[i][j]=arr[i-1][j]+arr[i][j-1];//状态转移方程
}
}
System.out.println(arr[3][4]);//35种
}
}
?解析:这是道很简单的动规问题,当然没学过动规的兄弟会觉得有点难。没学过动规的兄弟建议先从斐波那契数列开始学习动规。动规是蓝桥杯的高频考点之一,它出的动规可能会很难也可能会很简单,所以兄弟们对于简单的动规问题千万不能做错。
?4.猜字母(字符处理问题)
题目:
把abcd….s共19个字母组成的序列重复拼接106次,得到长度为2014的串。
接下来删除第1个字母(即开头的字母a),以及第3个,第5个等所有奇数位置的字符。
得到的新串再进行删除奇数位置字母的动作。如此下去,最后只剩下一个字母,请写出该字母。
思路1:采用字符串形式
public class 猜字母 {
public static void main(String[] args) {
StringBuilder a=new StringBuilder("abcdefghijklmnopqrs");
//StringBuilder效率更高
for (int i = 1; i <106 ; i++) {
a.append("abcdefghijklmnopqrs");
}
//重复拼接获得子串
while (a.length()>1){
int l=a.length()/2;
if (a.length()%2!=0) {
l++;
}
for (int i = 0; i <l; i++) {//注意这里是i++不是i+=2,因为待删除的数组下标在变化
a.deleteCharAt(i);
}
}
System.out.println(a);//q
}
}
?解析:首先这里我们用的是StringBuider,因为它的效率是最高的。这里我们才用字符串的一个好处是它自带的delete操作可以帮助我们删除元素,但正因如此也是我们容易掉坑的地方。当我们删除一个元素后,后续的元素会马上排上来,导致我们本该删除的元素的下标变化,导致了删掉了错误的元素。但其实也是有规律的,每删除一个元素后,后续所有待删除的元素都向左移动一格。比如有个字符串abcde,按照要求我们需要删掉ace这三个,a的下标为0删除后,原字符串变为bcde,这时本来下标为2的c变成了1,这时我们删掉c后再下一个待删除的元素e下标变为2了。于是本来需要隔一个再删除,却由于下标动态变化就只需要让i++而不是i+=2了。这里只需要考虑到长度为奇数时需要比偶数多删一次的问题即可,最后删剩的字符就是q。
思路2:采用数组形式
public class 猜字母02 {
public static void main(String[] args) {
char[] a=new char[2014];
int index=0;
for (int i = 0; i < 106; i++) {
for (int j = 0; j < 19; j++) {
a[index++]= (char) ('a'+j);//这里涉及到ascii表的字母转换
}
}
//采用数组形式存放
int len=2014;
while (len!=1){
int k=0;
for (int i = 1; i <len ; i+=2) {
a[k++]=a[i];
}
len=k;
}
System.out.println(a[0]);//q
}
}
?解析:用数组形式来做的话更好理解也不容易出错。把每次需要留下来的元素往前摆。用len来动态地保存这一段的长度,k是待插入的下标。每次需要保存的元素往前放,然后用len更新保留下来的数组长度,一次次往前移动,不要的元素放数组后面。最后循环结束后,数组的第一个元素就是我们剩下的元素q。
?5.立方变自身(简单枚举)
题目:观察下面的现象,某个数字的平方,按位累加仍然等于自身
1^3=1
8^3=512 5+1+2=8
17^3=4913 4+9+1+3=17
…
请你计算包括1,8,17在内,符合这个性质的正整数一共有多少个?
public class 立方自身 {
public static void main(String[] args) {
int count = 0;
//其实到最多到100就可以了,也可以加大范围枚举,会发现答案不会变多
for (int i = 1; i < 100; i++) {
if (sum((int) Math.pow(i, 3)) == i) {
count++;
}
}
System.out.println(count);//6
}
public static int sum(int x){//获得数x各个位相加的返回值
int count=0;
while(x>0){
count+=x%10;
x=x/10;
}
return count;
}
}
?解析:这道题就是普通的枚举题目,它的枚举范围也很好确定。当到100的三次方时,数就已经很大了,即使再往后枚举也不会让答案增多。不过为了更好确定,我们也可以把i的范围拉大继续枚举,会发现答案仍然也只有6个。
?6.三羊献瑞(7个for循环枚举问题)
题目:
观察下面的加法算式:
祥 瑞 生 辉
+ 三 羊 献 瑞
————————————
三 羊 生 瑞 气
public class 三羊祥瑞 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (i!=j)for (int k = 0; k < 10; k++) {
if (i!=k&&j!=k)for (int l = 0; l < 10; l++) {
if (i!=l&&j!=l&&k!=l)for (int m = 0; m < 10; m++) {
if (i!=m&&j!=m&&k!=m&&l!=m)for (int n = 0; n < 10; n++) {
if (i!=n&&j!=n&&k!=n&&l!=n&&m!=n)for (int o = 0; o < 10; o++) {
if (i!=o&&j!=o&&k!=o&&l!=o&&m!=o&&n!=o){
int x1=i*1000+j*100+k*10+l;
int x2=m*1000+n*100+o*10+j;
if (isOK(x1,x2,i,j,k,l,m,n,o)){
System.out.println(" "+x1);
System.out.println(" "+x2);
System.out.println(x1+x2);
}
}
}
}
}
}
}
}
}
}
public static boolean isOK(int x1,int x2,int i,int j,int k,int l,int m,int n,int o){
int count=x1+x2;
if (count<10000) return false;//如果加起来不是五位数可以直接返回false
int a=count%10;
if (a==i||a==j||a==k||a==l||a==m||a==n||a==o) return false;
count=count/10;
a=count%10;
if (a!=j) return false;
count=count/10;
a=count%10;
if (a!=k) return false;
count=count/10;
a=count%10;
if (a!=n) return false;
count=count/10;
a=count%10;
if (a!=m) return false;
return true;
}
}
?解析:这是一道非常非常经典的蓝桥真题枚举问题。最直接最暴力的方法就直接去写七个for循环分别将祥瑞生辉三羊献七个字枚举出来,再写一个判断答案是否符合要求的方法。思路很简单,但是步骤写起来需要小心。但其实这里我想说的是这里其实是可以优化的,两个四位数相加得到一个五位数。那么这个这个五位数的万位只可能是1,也就是三字其实就是1,既然祥加三得进位,三又是1,那么祥肯定就只能是9,进而再可得羊是0。大家可以和上面我贴出的答案对比就能看出来。这样其实我们的循环就少了几层了,但蓝桥杯做出答案才是目的,即使是7个for循环,但其实都是常数级的循环,瞬间就可以枚举出结果。
?7.加法变乘法(插乘枚举)
题目:
public class 加法变乘法 {
public static void main(String[] args) {
for (int i = 1; i <= 46; i++) {
for (int j = i + 2; j <= 48; j++) {
int count = i * (i + 1) + j * (j + 1);//一定要记得加括号
for (int k = 1; k <= 49; k++) {//将其余的数相加
if (k != i && k != i + 1 && k != j && k != j + 1) {//判断k不是我们前面已经用来相乘的数
count += k; //将剩余的数加起来
}
}
if (count == 2015) {
System.out.println(i);//得到10 16
}
}
}
}
}
?解析:这道题也是经典的插入乘法的枚举问题。比较难处理的是如何进行相加和放乘号的位置。我们需要通过两个循环去模拟左右乘号的放入问题,外循环遍历左括号可能的位置,内循环遍历右括号可能的位置。因为乘号不可以相邻,所以左括号可能的位置是1的后面到46的后面,右括号每次起始的位置是i+2,最多可以到达48的后面。然后将第一个乘号的乘积加上第二个乘号的乘积得到count,然后遍历加上剩余的元素最后判断值是否是我们的2015。最后得到的输出有10和16,10是题目已经给过的答案,所以另外一个答案就16。
?3.蓝桥典型枚举问题总结和做题经验
以上我抽选的都是蓝桥杯较容易拿分的枚举填空题,这是我们拿分的关键,也是最容易拿分的题目。因为枚举只要你不着急,大胆去尝试和猜想,耐心的考虑到全部的情况,就一定可以算出答案。也不用去想着怎么去优化代码,只要能得到答案,就去尝试。当然得到答案后也一定要去验证一下,代码的细节也要把握好,否则很容易得到错误答案。最最主要的,还是要多加练习,包括以上的题目和以及视频资源我都为大家准备好了。
由于资源视频和真题链接违规,需要的伙伴们直接私信我或者评论,马上回!!!有用的兄弟们麻烦三连,感谢!!!
文末小惊喜:
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/185857.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...