2020年蓝桥杯题目

前言

交了 300 不去感觉血亏,还是去参加吧…

滔博 🐮🍺 好吧,LPL 冲冲冲,预言一手 G2 爆冷干碎 LCK 哈哈哈哈哈

题目

门派制作

大意就是找出1 - 2020中数字2出现的个数

由于是填空题,直接遍历然后计算即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Main {
public static void main(String[] args){
int count = 0;
for(int i = 1; i <= 2020; i++){
int num = i;
while(num > 0){
int rest = num % 10;
if(rest == 2){
count++;
}
num = num / 10;
}
}
System.out.println(count);
}
}

算出的答案为624,这题其实在力扣上有基本一样的,可以直接遍历数位计算出来

面试题 17.06. 2 出现的次数 > 233. 数字 1 的个数

有兴趣的可以做做,我就做了第二题,虽然是看着题解做的 🤣

基本思路就是把数字分成左右两半进行计算,从而以O(n)复杂度(n为数字长度)

在第一题的控制台试了试,输出了624,那应该就是正确的

只能说暴力法天下第一好吧,只要我的电脑够快,复杂度就追不上我 🤣

2020

大意就是给你一个数组,对下面三种情况计数

  • 每行左到右出现2020
  • 每列上到下出现2020
  • 左上到右下对角线出现2020

同样,由于是填空题,所以依然暴力(因为想不出其他解法了 🤣)

这一题给了个txt文件,答的时候看了下,应该是300x300的数组

刚开始我认为我写不出来文件的读取,没想到查了查 api 文档竟然写出来了 🤣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class lanqiao_P2 {
public static void main(String[] args) {
String filePath = "D:\\2020.txt";
// 因为知道300x300了,这里就直接写死了。
int[][] array = new int[300][300];
int curLine = 0;
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
String line = br.readLine();
while (line != null) {
// 防止空格
line = line.trim();
for (int i = 0; i < line.length(); i++) {
array[curLine][i] = line.charAt(i) - '0';
}
curLine++;
line = br.readLine();
}
} catch (Exception e) {
e.printStackTrace();
} finally{
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

int count = 0;
// 遍历行
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length - 3; j++) {
if (array[i][j] == 2
&& array[i][j + 1] == 0
&& array[i][j + 2] == 2
&& array[i][j + 3] == 0) {
count++;
}
}
}
// 遍历列
for (int i = 0; i < array[0].length; i++) {
for (int j = 0; j < array.length - 3; j++) {
if (array[j][i] == 2
&& array[j + 1][i] == 0
&& array[j + 2][i] == 2
&& array[j + 3][i] == 0) {
count++;
}
}
}
// 遍历左上到右下
for (int i = 0; i < array.length - 3; i++) {
if (array[i][i] == 2
&& array[i + 1][i + 1] == 0
&& array[i + 2][i + 2] == 2
&& array[i + 3][i + 3] == 0) {
count++;
}
}
System.out.println(count);
}
}

这题忘了答案是啥来着了…

蛇形填空

大意就是,数字按下面的规律,求2020列的数字

1
2
3
4
5
6
 1  2  6  7 15 ...
3 5 8 14 ...
4 9 13 ...
10 12 ...
11 ...
...

这题我没写代码来计算,我看着规律的…

首先要确定2020列最少要多少次蛇形

看样例可以知道

33列可以计算出22

55列可以计算出33

那么计算2020列,应该需要3939列,即20 * 2 - 1

然后又可以看出每次蛇形的结束的值就是累加1+2+...+n的值

1
2
1  2  ...
3 ...

此时最后的值应该是 1 + 2 = 3

那么第39次蛇形的结束的值应该就是1 + 2 + ... + 39 = 780

起始值应该就是 780 + 1 - 39 = 742

根据样例的规律,斜着的奇数行的结束是在第一行,斜着的偶数行的结束在第一列,也就是

1
2
3
4
5
6
7
 1  2  6  7 15 ... 780
3 5 8 14 ... 779
4 9 13 ... 778
10 12 ... ...
11 ... 744
... 743
742

然后取中间的值,就是2020列的值了,也就是761

(感觉是正确的…)

七段码

大意就是用发光二极管来表示字符串,问能表示多少(画的跟屎一样 😂)

1
2
3
4
5
----
| |
----
| |
----

有点类似我们数字时钟那个样子,如下

要求就是亮的部分不能断层,比如下面这些

1
2
3
4
5
6
 ----      ----      ----      ----
| | |
---- ----
| |
----
(可以) (可以) (可以) (不可以)

这题做不出来 😂,太菜了,最后数了数亮 1 个到亮全部的个数,就提交了…

排序次数

说的是冒泡排序,求一个交换次数为100的最短且字典序拍最前的字符串

比如bnl需要交换1次(nl互换)

我的想法就是,比如dcba这种全倒排需要的次数是最大的,这个交换的次数就是

3([d,c]->[d,b]->[d,a])+2([c,b]->[c,a])+1([b,a]) = 6

所以可以知道要超过100次,那么此时最短的字符串应为onmlkjihgfedcba

这时的比较次数为14+13+...+1=105,如果是长度13,那么结果只有91,不符合题意

但此时感觉不是字典序最短的,当时想着把onmlkjihgfedcba最前面的两个变成有序地来分析

nomlkjihgfedcbano交换,影响o的的交换次数,而不影响n的交换次数

  • onmlkjihgfedcbao冒泡到最末尾时,为nmlkjihgfedcbao,此时交换14
  • nomlkjihgfedcbao冒泡到最末尾时,为nmlkjihgfedcbao,此时交换13

字典序nomlkjihgfedcba是小于onmlkjihgfedcba的,所以还有优化的空间,

也就是前面多少个字符顺序了会最接近次数100

又试了下前面3个顺序时,mnolkjihgfedcba

  • 对于o,少比较2
  • 对于n,少比较1

那么就少了3次,还是符合,但是如果前面4个有序,此时少了3+2+1=6次,就不符合了

综上,我的答案为mnolkjihgfedcba,一通分析感觉相当有道理(还是有点小慌 🤣)

成绩分析

这题是不是有圈套,有点太基础的感觉…

给 n 个分数,0-100,计算最大值,最小值和平均值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int max = -1;
int min = 101;
int sum = 0;
for (int i = 1; i <= n; i++) {
int cur = in.nextInt();
max = Math.max(max, cur);
min = Math.min(min, cur);
sum += cur;
}
System.out.println(max);
System.out.println(min);
// 保留2位小数
System.out.println(Math.round(sum * 1.0 / n * 100) * 1.0 / 100);
}
}

单词分析

emmm,这题是不是也有圈套???

给定一个字符串,计算出现次数最多的字符和它的次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
int[] map = new int[26];
for (int i = 0; i < s.length(); i++) {
map[s.charAt(i) - 'a']++;
}
char maxC = ' ';
int count = 0;
for (int i = 0; i < map.length; i++) {
if (map[i] > count) {
count = map[i];
maxC = (char) (i + 'a');
}
}
System.out.println(maxC);
System.out.println(count);
}
}

数字三角形

这题和之前那个金字塔数字求和很像

从上往下找累加最大值,比如

1
2
3
4
10
10 1
10 2 3
10 3 4 5

上面最大值为40,但是这题还有一个限制,就是往左和往右的次数之差不能超过1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.Scanner;

public class Main {

static int max = 0;

public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[][] array = new int[n][n];
for (int i = 0; i < array.length; i++) {
for (int j = 0; j <= i; j++) {
array[i][j] = in.nextInt();
}
}
max = 0;
dfs(array, 0, 0, 0, 0, 0);
System.out.println(max);
}

static void dfs(int[][] array, int n, int j, int left, int right, int curSum) {
// 剪枝
if (left > array.length / 2 || right > array.length / 2) {
return;
}
if (n == array.length - 1) {
max = Math.max(max, curSum + array[n][j]);
System.out.println(left + "-" + right);
return;
}
dfs(array, n + 1, j, left + 1, right, curSum + array[n][j]);
dfs(array, n + 1, j + 1, left, right + 1, curSum + array[n][j]);
}
}

字串分值和

这题 emmm,用了不知道叫不叫方法的方法

给定一个字符串(只包含小写字母),计算它所有字串的分值的和

分值的计算,比如对于ababc

分值就是该字符串不重复字符的个数,对于上面这个,也就是3

我的想法就是双重遍历,记忆前一个字串的分值,然后累加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Arrays;
import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine().trim();
int[] map = new int[26];
int sum = 0;
for (int i = 0; i < s.length(); i++) {
Arrays.fill(map, 0);
int curSum = 0;
for (int j = i; j < s.length(); j++) {
int index = s.charAt(j) - 'a';
if (map[index] == 0) {
map[index]++;
curSum++;
}
sum += curSum;
}
}
System.out.println(sum);
}
}

装饰珠

这个真没看懂,题目都没读懂,回来基本上就忘了

给定6件装备,每件装备有n个镶嵌孔,镶嵌孔有等级,可以镶嵌不大于这个等级的镶嵌珠

镶嵌镶嵌珠可以产生价值,相同的镶嵌珠可以增加价值

给定 m 种镶嵌珠,给定镶嵌 k 个第 i 种镶嵌珠产生的价值,

6件装备产生的最大价值

不会…