蓝桥杯(10道题)
jdk 8
main函数
1.填空题(只需要给答案)
2道,每题5分
2.代码题(需要提交代码)
由易到难
Java:尚硅谷(Java数据结构和算法) Python:清华大学(数据结构和算法) 大话数据结构和算法(第四版) 刷题网站: 1.洛谷(难)刷官方题单 2.北京大学 poj 3.acwing 4.力扣 暴力递归+暴力搜素+真题
一、循环(前三道题涉及)
1. for循环
一般能在题目里找到循环次数
2. while循环
只知道循环条件,不知道循环次数
在考察循环时,还会涉及到集合、字符串等知识等知识点的用用。 例如:
对字符串一般考察常用函数。字符串转字符数组,判断结尾等。
集合一般考察特性:
list:有序可重复
set:无序不可重复
map: key-value键值对(key不能为空,不能重复)
例题1
题目描述:有些数字的立方的末尾正好是该数字本身。 比如:1,4,5,6,9,24,25,…
请你计算一下,在10000以内的数字中(指该数字,并非它立方后的数值),符合这个特征的正整数一共有多少个。
请提交该整数,不要填写任何多余的内容。
public class Demo2 { public static void main(String args[]) { int cubedResult, num = 0; for (int x = 1; x <= 10000; x++) { cubedResult = x * x * x;//计算变量 x 的立方并将结果存储在 cubedResult 中。 String xStr = "" + x;//将整数变量 x 转换为字符串类型,存储在 xStr 中。 String cubedStr = "" + cubedResult; boolean endsWithX = cubedStr.endsWith(xStr);//检查 cubedStr 是否以 xStr 结尾,并将结果存储在 endsWithX 中。 if (endsWithX) { num++; } } System.out.println(num); } }
例题2
public class Demo3 { public static void main(String args[]){ int length = 2019; int width=324; int count=0;//切出正方形的个数 while(true){ if(length>width){//长大于宽 length=length-width; count++; }else if(length<width){//长小于宽 width=width-length; count++; }else if(length==width&&width!=0){ count ++; width-=width; length-=length; }else if(width==0){ break; } } System.out.println(count); } } 结果:21 Process finished with exit code 0
例题3
TIP:
-
循环的终止条件已知==总工资>=108元,用while循环
-
等差数列(直接暴力解题)
public class Demo4 { public static void main(String[] args) { int sum=0;//总钱数 int i=1;//每天挣得钱 int day=0;//总天数 while(true){ sum+=i; day+=1; if(sum>=108){ break; } i+=2;//后一天比前一天多挣2块钱 } System.out.println(day); } } 结果:11 Process finished with exit code 0
例题4
TIP(*4是因为拿了一堆,剩下4堆):
-
用while循环(满足下列条件结束):
1 .n%5=1 a=(n-1)/5*4
2 .a%5=2 b=(a-2)/5*4
3 .b%5=3 c=(b-3)/5*4
4 .c%5=4 d=(c-4)/5*4
5 .d%5=0 d>0
public class Demo5 { /* 1 .n%5=1 a=(n-1)/5*4 2 .a%5=2 b=(a-2)/5*4 3 .b%5=3 c=(b-3)/5*4 4 .c%5=4 d=(c-4)/5*4 5 .d%5=0 d>0 */ public static void main(String[] args) { int n=1;//香蕉数量 while(true){ if(n%5==1){ int a=(n-1)/5*4; if(a%5==2){ int b=(a-2)/5*4; if(b%5==3){ int c=(b-3)/5*4; if(c%5==4){ int d=(c-4)/5*4; if(d%5==0 && d>0){ break; } } } } } n++; } System.out.println(n); } } 3141 Process finished with exit code 0
3.字符串循环和集合的使用
对集合考察集中在集合的特性和功能。set唯一性。list有序性。以及集合元素的个数。
例题1:
TIP(set的唯一性,去除重复的子串):
-
下标0截取范围:【0,最大下标】
-
下标1截取范围:【1,最大下标】
截取的方法:subString(i,j)截取子串
public class Demo6 { public static void main(String[] args) { String string="0100110001010001"; HashSet<Object> set=new HashSet<>();//去重 for(int i=0;i<string.length();i++){//从第几个下标开始截取 for(int j=i;j<string.length();j++){ String s= string.substring(i,j+1); set.add(s); } System.out.println(set.size());//打印去重后的个数 } } } 结果:100
例题2:
找到一个整数i,使得i的平方和i的立方组成的字符串恰好包含10个唯一的字符,然后输出该整数i的值。在循环中,代码逐个递增检查i的值,直到找到满足条件的整数为止。
import java.util.HashSet; public class Demo2 { public static void main(String args[]) { int i = 1; while (true) { HashSet<Object> set = new HashSet<>(); int ping = i * i; int li = i * i * i; String string = ""+ping + li ; if (string.length() == 10) { char[] cs = string.toCharArray(); for (int j = 0; j < 10; j++) { set.add(cs[j]); } if (set.size() == 10) { System.out.println(i); break; } } i++; } } } 结果:69
4.循环求质数
-
质数是只能被1和它本身整除的数字。最小的质数是2
-
如何判断一个数字n是不是质数:找一下【2,n-1】有没有能被n整除的数字,有就不是质数。
-
整除:n对数字取余为0
例题
public class Demo61 { public static void main(String[] args) { ArrayList<Object> list = new ArrayList<>(); for (int i = 2; i <= 20000; i++) { int a = 0;//记录有没有除了1和它本身之外可以整除的数字 for (int j = 2; j <i; j++) { if (i % j == 0) { a++; break;//只要找到一个能被整除的就退出内层循环,提高运算效率 } } if (a == 0) {//没有能被整除的 list.add(i); } System.out.println(list.get(2022)); } } } 结果: 17597
二、排序与算法
1.排序
在一维数组中,排序是很重要的。冒泡排序,插入排序,选择排序(排序的思维不同)
冒泡排序
第一趟结束后最大的数字出现在最后一位(然后不用参与排序),第二趟结束倒数第二大的数字出现在倒数第二位(不用参与排序)
原理:比较两个相邻的元素,将较大的值交换到右边
2 8 7 5 9 4 3
第一趟:
第一次:比较2和8 (不需要交换)
第二次:比较8和7,(将8和7交换位置:2 7 8 5 9 4 3)
第三次:比较8和5,(将8和5交换位置:2 7 5 8 9 4 3)
第四次:比较8和9,(不需要交换)
第五次:比较9和4,(将9和4交换位置 :2 7 5 8 4 9 3)
第六次:比较9和3,(将9和3交换位置:2 7 5 8 4 3 9)
第二趟:
第一次:比较2和7(不需要交换)
第二次:比较7和5(需要交换 2 5 7 8 4 3 9)
第三次:比较7和8(不需要交换)
第四次:比较8和4(需要交换 2 5 7 4 8 3 9)
第五次:比较8和3(需要交换 2 5 7 4 3 8 9)
第六次:比较8和9(不需要交换)?
第三趟:
第一次:比较2和5(不需要交换)
第二次:比较5和7(不需要交换)
第三次:比较7和4(需要交换 2 5 4 7 3 8 9)
第四次:比较7和3(需要交换 2 5 4 3 7 8 9)
第五次:比较7和8(不需要交换)
第六次:比较7和9(不需要交换)
public class Demo11 { public static void main(String[] args) { //外层for循环控制趟,内层控制次数 int a[]={10,1,35,61,89,36,55}; for (int i = 0; i < a.length-1-i; i++) {//趟的次数是确定的 for (int j = 0; j <a.length-1; j++) { //判断相邻的两个数字 if(a[j]>a[j+1]){ //交换位置 int k = a[j]; a[j] = a[j+1]; a[j+1] = k; } } } for(int i=0;i<a.length;i++){ System.out.println(a[i]+"");//遍历 } } }
选择排序
原理:
第一次:从未排序的数据元素里面,选出一个最小的(最大的)的元素,然后和第一位元素交换位置;
第二次:从未排序的数据元素里面,选出一个第二小的(第二大的)的元素,然后和第二位元素交换位置;
。。。。以此类推
public class Demo31 { public static void main(String[] args) { int a[] = {2, 9, 5, 0, 1, 3, 6, 8}; int begin = 0; int end = a.length - 1; while (begin < end) { int min = a[begin];//min用来存储数组元素中的最小值 int t = begin;//min的下标 for (int i = begin; i <= end; i++) { if (min > a[i]) { min = a[i]; t = i; } } a[t] = a[begin]; a[begin] = min; begin++; } for (int i = 0; i < a.length; i++) { System.out.println(a[i] + "");//遍历 } } }
插入排序
原理:将数列分为两个部分:排好序的数列 未排序的数列
在未排序的数列里,挨个去插入到排好序的数列里面
public class Demo22 { public static void main(String[] args) { int a[] = {2, 1, 6, 4, 9, 7, 6, 8}; //为排好序的数组 for (int i = 1; i < a.length; i++) { int k = a[i];//哨兵。从数组第二位元素开始,每一循环向后移动一位存储元素,将这个数插入排号数的数列中 int j = i - 1;//排好序数列中的最后一位元素的下标(i是未排好序里面的第一位) while (j >= 0 && k < a[j]) {//哨兵要存在左边比他小,右边比它大 a[j + 1] = a[j];//给哨兵插入腾出位置 j--;//用j记录哨兵最终插入的位置 } a[j + 1] = k;//哨兵插入 } for (int i = 0; i < a.length; i++) { System.out.println(a[i] + "");//遍历 } } }
2.排序
递归
函数/方法 直接/间接 的调用本身。一般用来在原来的基础上加减乘除等操作
案例:斐波那契数列:
1 1 2 3 5 8 13……第一和第二个数字是1,其他数字等于前两个数字之和。Fn=F(n-1)+F(n-2)
代码:计算第n位的斐波那契数字
//递归:代码简洁,但是涉及的运算会随着递归层数的增加而指数增长,效率低下 public static int Fn(int n){ if(n==1||n==2){ return 1; } return Fn(n-1)+Fn(n-2); } }
例题
第20行第20列相当于这个数列的第20位数字。
public class Demo33 { public static void main(String[] args) { System.out.println(snack(20)); } public static int snack(int n){ if(n==1){ return 1; } return snack(n-1)+4*(n-1); } }
记得找规律
问题:递归和循环的关系?
一道题可以用递归(代码简洁、但是时间复杂度大)解答,也可以换成循环(代码量变多、运算资源减少了、降低了时间复杂度)来解决
如果发现题目使用递归超出了限制,那么:
-
换循环;
-
加字典;
public class Demo0 { public static void main(String[] args) { System.out.println(Fn(20)); } //递归:代码简洁,但是涉及的运算会随着递归层数的增加而指数增长,效率低下 public static int Fn(int n){ if(n==1||n==2){ return 1; } return Fn(n-1)+Fn(n-2); } } 思考:用辗转相除法求最大公约数