PTA L1系列题解(C语言)(L1_097 -- L1_104)

前言:

这就是目前为止PTA团体赛题库中L1的所有题目了,对于L2的题目可能在后面以一个很慢的速度更新,我可能会先转向Python爬虫的内容去学习一下, 然后可能还会做单片机方面的内容,大家也可以关注一下我的 Python爬虫单片机的专栏内容,感谢支持。

L1-097 编程解决一切

题目内容:

L1-097 编程解决一切 - 团体程序设计天梯赛-练习集

编程解决一切 ------ 本题非常简单,就请你直接在屏幕上输出这句话:"Problem? The Solution: Programming."。

输入格式:

本题没有输入。

输出格式:

在一行中输出 Problem? The Solution: Programming.

输入样例:

输出样例:

Problem? The Solution: Programming.

解题思路:

略。

C代码展示:

cpp 复制代码
#include <stdio.h>

int main()
{
	printf("Problem? The Solution: Programming.\n");

	return 0;
}

L1-098 再进去几个人

题目内容:

L1-098 再进去几个人 - 团体程序设计天梯赛-练习集

数学家、生物学家和物理学家坐在街头咖啡屋里,看着人们从街对面的一间房子走进走出。他们先看到两个人进去。时光流逝。他们又看到三个人出来。

物理学家:"测量不够准确。"

生物学家:"他们进行了繁殖。"

数学家:"如果现在再进去一个人,那房子就空了。"

下面就请你写个程序,根据进去和出来的人数,帮数学家算出来,再进去几个人,那房子就空了。

输入格式:

输入在一行中给出 2 个不超过 100 的正整数 A 和 B,其中 A 是进去的人数,B 是出来的人数。题目保证 B 比 A 要大。

输出格式:

在一行中输出使得房子变空的、需要再进去的人数。

输入样例:

4 7

输出样例:

3

解题思路:

略。

C代码展示:

cpp 复制代码
#include <stdio.h>

int main()
{
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d\n", b - a);

    return 0;
}

L1-099 帮助色盲

题目内容:

L1-099 帮助色盲 - 团体程序设计天梯赛-练习集

在古老的红绿灯面前,红绿色盲患者无法分辨当前亮起的灯是红色还是绿色,有些聪明人通过路口的策略是这样的:当红灯或绿灯亮起时,灯的颜色无法判断,但前方两米内有同向行走的人,就跟着前面那人行动,人家走就跟着走,人家停就跟着停;如果当前是黄灯,那么很快就要变成红灯了,于是应该停下来。麻烦的是,当灯的颜色无法判断时,前方两米内没有人......

本题就请你写一个程序,通过产生不同的提示音来帮助红绿色盲患者判断当前交通灯的颜色;但当患者可以自行判断的时候(例如黄灯或者前方两米内有人),就不做多余的打扰。具体要求的功能为:当前交通灯为红灯或绿灯时,检测其前方两米内是否有同向行走的人 ------ 如果有,则患者自己可以判断,程序就不做提示;如果没有,则根据灯的颜色给出不同的提示音。黄灯也不需要给出提示。

输入格式:

输入在一行中给出两个数字 A 和 B,其间以空格分隔。其中 A 是当前交通灯的颜色,取值为 0 表示红灯、1 表示绿灯、2 表示黄灯;B 是前方行人的状态,取值为 0 表示前方两米内没有同向行走的人、1 表示有。

输出格式:

根据输入的状态在第一行中输出提示音:dudu 表示前方为绿灯,可以继续前进;biii 表示前方为红灯,应该止步;- 表示不做提示。在第二行输出患者应该执行的动作:move 表示继续前进、stop 表示止步。

输入样例 1:

0 0

输出样例 1:

biii
stop

输入样例 2:

1 1

输出样例 2:

-
move

解题思路:

这题主要是一个分支的条件判断的书写。

按照题目,咱们一点点看:

但当患者可以自行判断的时候(例如黄灯或者前方两米内有人 ),就不做多余的打扰。具体要求的功能为:当前交通灯为红灯或绿灯时,检测其前方两米内是否有同向行走的人 ------ 如果有,则患者自己可以判断 ,程序就不做提示 ;如果没有 ,则根据灯的颜色给出不同的提示音黄灯不需要给出提示

对于这里,咱们可以先按照能不能自己进行判断来分类,也就是有没有同向的人 或者 黄灯, 放在代码里就是b == 1 || a == 2 。

然后再对红灯和绿灯 进行判断,在代码中也就是 a == 1 和 a == 0 输出结果。

C代码展示:

cpp 复制代码
#include <stdio.h>

int main()
{
    int a, b;
    scanf("%d %d", &a, &b);
    if (b == 1 || a == 2){
        printf("-\n");
        if (a == 1) printf("move");
        else printf("stop");
    }
    else{
        if (a == 0) printf("biii\nstop");
        else printf("dudu\nmove");
    }

    return 0;
}

L1-100 四项全能

题目内容:

L1-100 四项全能 - 团体程序设计天梯赛-练习集

新浪微博上有一个帖子给出了一道题:全班有 50 人,有 30 人会游泳,有 35 人会篮球,有 42 人会唱歌,有 46 人会骑车,至少有( )人四项都会。

发帖人不会做这道题,但是回帖有会做的:每一个才艺是一个技能点,一共是 30 + 35 + 42 + 46 = 153 个技能点,50 个人假设平均分配,每人都会 3 个技能那也只有 150,所以至少有 3 人会四个技能。

本题就请你写个程序来自动解决这类问题:给定全班总人数为 n,其中有 m 项技能,分别有 k1​、k2​、......、km​ 个人会,问至少有多少人 m 项都会。

输入格式:

输入在第一行中给出 2 个正整数:n(4≤n≤1000)和 m(1<m≤n/2),分别对应全班人数和技能总数。随后一行给出 m 个不超过 n 的正整数,其中第 i 个整数对应会第 i 项技能的人数。

输出格式:

输出至少有多少人 m 项都会。

输入样例:

50 4
30 35 42 46

输出样例:

3

解题思路:

这道题你可以将每个人会的某个技能看成一个元素,例如有一个人会三个技能,那就可以将他看成是三个元素。

按照这种想法,他会所有技能的人最少有的人数就是默认所有人会 m-1 个技能,剩下的就是会第 m 个技能的人,也就是会 m 项技能的人数。

但是要注意 ,他所有人加起来,可能会比默认所有人会 m - 1 个技能的人少,也就是相减之后会成负数。这时候当然不能输出这个答案,这时候应该输出 0

C代码展示:

cpp 复制代码
#include <stdio.h>

int main()
{
	int n, m, sum=0;
    scanf("%d %d", &n, &m);
    for (int i=0; i<m; i++){
        int a;
        scanf("%d", &a);
        sum += a;
    }
    if (sum >= n*(m-1)) printf("%d\n", sum - n*(m-1));
    else printf("0\n");
    
	return 0;
}

L1-101 别再来这么多猫娘了!

题目内容:

L1-101 别再来这么多猫娘了! - 团体程序设计天梯赛-练习集

以 GPT 技术为核心的人工智能系统出现后迅速引领了行业的变革,不仅用于大量的语言工作(如邮件编写或文章生成等工作),还被应用在一些较特殊的领域------例如去年就有同学尝试使用 ChatGPT 作弊并被当场逮捕(全校被取消成绩)。相信聪明的你一定不会犯一样的错误!

言归正传,对于 GPT 类的 AI,一个使用方式受到不少年轻用户的欢迎------将 AI 变成猫娘:

部分公司使用 AI 进行网络营销,网友同样乐于使用"变猫娘"的方式进行反击。注意:图中内容与题目无关,如无法看到图片不影响解题。

当然,由于训练数据里并不区分道德或伦理倾向,因此如果不加审查,AI 会生成大量的、不一定符合社会公序良俗的内容。尽管关于这个问题仍有争论,但至少在比赛中,我们还是期望 AI 能用于对人类更有帮助的方向上,少来一点猫娘。

因此你的工作是实现一个审查内容的代码,用于对 AI 生成的内容的初步审定。更具体地说,你会得到一段由大小写字母、数字、空格及 ASCII 码范围内的标点符号的文字,以及若干个违禁词以及警告阈值,你需要首先检查内容里有多少违禁词,如果少于阈值个,则简单地将违禁词替换为<censored>;如果大于等于阈值个,则直接输出一段警告并输出有几个违禁词。

输入格式:

输入第一行是一个正整数 N (1≤N≤100),表示违禁词的数量。接下来的 N 行,每行一个长度不超过 10 的、只包含大小写字母、数字及 ASCII 码范围内的标点符号的单词,表示应当屏蔽的违禁词。

然后的一行是一个非负整数 k (0≤k≤100),表示违禁词的阈值。

最后是一行不超过 5000 个字符的字符串,表示需要检查的文字。

从左到右处理文本,违禁词则按照输入顺序依次处理;对于有重叠的情况,无论计数还是替换,查找完成后从违禁词末尾继续处理。

输出格式:

如果违禁词数量小于阈值,则输出替换后的文本;否则先输出一行一个数字,表示违禁词的数量,然后输出He Xie Ni Quan Jia!

输入样例1:

5
MaoNiang
SeQing
BaoLi
WeiGui
BuHeShi
4
BianCheng MaoNiang ba! WeiGui De Hua Ye Keyi Shuo! BuYao BaoLi NeiRong.

输出样例1:

BianCheng <censored> ba! <censored> De Hua Ye Keyi Shuo! BuYao <censored> NeiRong.

输入样例2:

5
MaoNiang
SeQing
BaoLi
WeiGui
BuHeShi
3
BianCheng MaoNiang ba! WeiGui De Hua Ye Keyi Shuo! BuYao BaoLi NeiRong.

输出样例2:

3
He Xie Ni Quan Jia!

输入样例3:

2
AA
BB
3
AAABBB

输出样例3:

<censored>A<censored>B

输入样例4:

2
AB
BB
3
AAABBB

输出样例4:

AA<censored><censored>

输入样例5:

2
BB
AB
3
AAABBB

输出样例5:

AAA<censored>B

(难绷,题目好长......)

解题思路:

本题大体的思路和前一篇里的L1-094 剪切粘贴 还有另一篇里的L1-064 估值一亿的AI核心代码这两题比较类似,然后我们的思路整体就是查找违禁词,然后替换,比较需要注意的是题目里的这句话:

从左到右处理文本,违禁词则按照输入顺序依次处理 ;对于有重叠的情况,无论计数还是替换,查找完成后从违禁词末尾继续处理。

然后其他的可以先再看看另外两篇的内容,再来写这个,相信是会有帮助的,虽然那两题也很麻烦。其他的可以先参考一下我的代码。

  1. 读取将要审查的关键词数量n
  2. 使用gets函数读取n个关键词,存入数组jin中。
  3. 读取允许的最大违规次数k
  4. 使用gets函数读取需要审查的长字符串s
  5. 对于每个关键词,使用strstr函数在长字符串s中查找匹配项。如果找到匹配项,则进行替换,并更新违规次数cnt
  6. 如果在长字符串s中找到了关键词,则将其替换为"-",并更新ans字符串。
  7. 如果违规次数cnt大于或等于k,则输出违规次数和提示信息"He Xie Ni Quan Jia!"。
  8. 如果违规次数cnt小于k,则输出审查后的长字符串s,其中违规部分被替换为"<censored>"。

注意点:

对于替换词,不要选用字母或者数字,也不要用题目给的替换词,会导致重复判断,然后疯狂套娃,导致超出。

C代码展示:

cpp 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    int n, k, cnt=0; // 定义变量n(关键词数量),k(允许的最大违规次数),cnt(违规次数计数器)
    char jin[105][20] = {0}, s[100000] = {0}, ans[100000] = {0}; // 定义关键词数组jin,原始内容字符串s,审查后内容字符串ans
    scanf("%d", &n); // 读取关键词数量
    getchar(); // 读取并丢弃换行符
    for (int i = 0; i < n; i++) gets(jin[i]); // 使用gets函数读取关键词
    scanf("%d", &k); // 读取允许的最大违规次数
    getchar(); // 读取并丢弃换行符
    gets(s); // 使用gets函数读取原始内容字符串
    for (int i = 0; i < n; i++) {
        while (1) {
            char *p = strstr(s, jin[i]); // 在s中查找关键词
            if (p == NULL) break; // 如果没有找到,跳出循环
            cnt++; // 违规次数加1
            char temp = *p; // 保存找到的关键词的第一个字符
            *p = '\0'; // 将关键词的第一个字符替换为字符串结束符,临时截断字符串
            strcpy(ans, s); // 复制s到ans
            *p = temp; // 恢复s
            strcat(ans, "-"); // 在ans中添加"-"作为标记,需要在这里更换替换词。
            strcat(ans, p + strlen(jin[i])); // 在ans中添加关键词后的内容
            strcpy(s, ans); // 更新s为审查后的内容
        }
    }
    if (cnt >= k) printf("%d\nHe Xie Ni Quan Jia!\n", cnt); // 如果违规次数大于或等于k,输出违规次数和提示信息
    else {
        for (int i = 0; i < strlen(s); i++) {
            if (s[i] == '-') {
                printf("<censored>"); // 输出"<censored>"
            }
            else {
                printf("%c", s[i]); // 输出审查后的字符
            }
        }
    }

    return 0;
}

L1-102 兰州牛肉面

题目内容:

L1-102 兰州牛肉面 - 团体程序设计天梯赛-练习集

兰州牛肉面是历史悠久的美食,根据牛肉面的宽窄、配料的种类,可以细分为上百个不同的品种。你进到兰州的任何一家牛肉面馆,只说:"来一碗牛肉面!"就好像进到加州的咖啡馆说"来一杯咖啡"一样,会被店主人当成外星人......

本题的任务是,请你写程序帮助一家牛肉面馆的老板统计一下,他们一天卖出各种品种的牛肉面有多少碗,营业额一共有多少。

输入格式:

输入第一行给出一个正整数 N(≤100),为牛肉面的种类数量。这里为了简单起见,我们把不同种类的牛肉面从 1 到 N 编号,以后就用编号代替牛肉面品种的名称。第二行给出 N 个价格,第 i 个价格对应第 i 种牛肉面一碗的单价。这里的价格是 [0.01, 200.00] 区间内的实数,以元为单位,精确到分。

随后是一天内客人买面的记录,每条记录占一行,格式为:

品种编号 碗数

其中碗数保证是正整数。当对应的 品种编号0 时,表示输入结束。这个记录不算在内。

输出格式:

首先输出 N 行,第 i 行输出第 i 种牛肉面卖出了多少碗。最后一行输出当天的总营业额,仍然是以元为单位,精确到分。题目保证总营业额不超过 106。

输入样例:

5
4.00 8.50 3.20 12.00 14.10
3 5
5 2
1 1
2 3
2 2
1 9
0 0

输出样例:

10
5
5
0
2
126.70

解题思路:

这道题和上面的猫娘比起来真的是小菜一碟了,明明同样是15分题,但难度差的很多。

OK,咱也不废话了,简单说一下我的解题方法。

首先,是对当输入 0 0 时才停止输入这点,就需要边输入边判断。

然后,在它每次输入的类型的面的销售量进行统计,以及销售额进行累加。

最后,输出上面的数即可。

整体而言还是简单的。

注意: 这里用来存单价和总营业额 的参数类型一定要是double型,否则它可能会因为精度原因过不了测试点三。

C代码展示:

cpp 复制代码
#include <stdio.h>

int main()
{
	int n, _n, cnt, earn[105]={0};
    double price[105]={0}, sum=0;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%lf", &price[i]);
    scanf("%d %d", &_n, &cnt);
    while (!(_n == 0 && cnt == 0)){ //边输入边判断。
        earn[_n] += cnt; //销售数量统计
        sum += cnt * price[_n]; //销售额累加
        scanf("%d %d", &_n, &cnt);
    }
    for (int i = 1; i <= n; i++)
    {
        printf("%d\n", earn[i]); //输出每种类型的销售数量。
    }
    printf("%.2lf", sum); //输出销售额。
    

	return 0;
}

L1-103 整数的持续性

题目内容:

L1-103 整数的持续性 - 团体程序设计天梯赛-练习集

从任一给定的正整数 n 出发,将其每一位数字相乘,记得到的乘积为 n1​。以此类推,令 ni+1​ 为 ni​ 的各位数字的乘积,直到最后得到一个个位数 nm​,则 m 就称为 n 的持续性 。例如 679 的持续性就是 5,因为我们从 679 开始,得到 6×7×9=378,随后得到 3×7×8=168、1×6×8=48、4×8=32,最后得到 3×2=6,一共用了 5 步。

本题就请你编写程序,找出任一给定区间内持续性最长的整数。

输入格式:

输入在一行中给出两个正整数 a 和 b(1≤a≤b≤109 且 (b−a)<103),为给定区间的两个端点。

输出格式:

首先在第一行输出区间 [a,b] 内整数最长的持续性。随后在第二行中输出持续性最长的整数。如果这样的整数不唯一,则按照递增序输出,数字间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

500 700

输出样例:

5
679 688 697

解题思路:

对于这道题,题目要求的数据量其实没有那么大,所以正常的暴力解法就能解决问题,然后它主要就是在做两件事情:

1.逐位相乘。

2.记录最长持续性和数据。

测试点1 :需要注意的是对于本身就是个位数的值要注意以下,如果你的代码不能处理这部分,需要进行一定的修改。

C代码展示:

cpp 复制代码
#include <stdio.h>

int main()
{
	int a, b, max=0, ans[10000]={0}, k=0;
    scanf("%d %d", &a, &b);
    for (int i=a; i<=b; i++){ 
        int cnt=0, num=i, temp=1;
        for(; num >= 10; cnt++, temp=1){ //判断这个数还能不能继续进行处理。
            for (; num > 0; num/=10){ //逐位相乘。
                temp *= num%10;
            }
            num = temp;
        }
        if (cnt > max){ //找最长的值
            k=1;
            max = cnt;
            ans[0] = i;
        }
        else if (cnt == max){
            ans[k] = i; //将数据记录下来
            k++;
        }
    }

    printf("%d\n", max);
    for (int i = 0; i < k; i++)
    {
        if (i == 0) printf("%d", ans[i]);
        else printf(" %d", ans[i]);
    }
    
	return 0;
}

L1-104 九宫格

题目内容:

L1-104 九宫格 - 团体程序设计天梯赛-练习集

九宫格是一款数字游戏,传说起源于河图洛书,现代数学中称之为三阶幻方。游戏规则是:将一个 9×9 的正方形区域划分为 9 个 3×3 的正方形宫位,要求 1 到 9 这九个数字中的每个数字在每一行、每一列、每个宫位中都只能出现一次。

本题并不要求你写程序解决这个问题,只是对每个填好数字的九宫格,判断其是否满足游戏规则的要求。

输入格式:

输入首先在第一行给出一个正整数 n(≤10),随后给出 n 个填好数字的九宫格。每个九宫格分 9 行给出,每行给出 9 个数字,其间以空格分隔。

输出格式:

对每个给定的九宫格,判断其中的数字是否满足游戏规则的要求。满足则在一行中输出 1,否则输出 0。

输入样例:

3
5 1 9 2 8 3 4 6 7
7 2 8 9 6 4 3 5 1
3 4 6 5 7 1 9 2 8
8 9 2 1 4 5 7 3 6
4 7 3 6 2 8 1 9 5
6 5 1 7 3 9 2 8 4
9 3 4 8 1 6 5 7 2
1 6 7 3 5 2 8 4 9
2 8 5 4 9 7 6 1 3
8 2 5 4 9 7 1 3 6
7 9 6 5 1 3 8 2 4
3 4 1 6 8 2 7 9 5
6 8 4 2 7 1 3 5 9
9 1 2 8 3 5 6 4 7
5 3 7 9 6 4 2 1 8
2 7 9 1 5 8 4 6 3
4 5 8 3 2 6 9 7 1
1 6 3 7 4 9 5 8 3
81 2 5 4 9 7 1 3 6
7 9 6 5 1 3 8 2 4
3 4 1 6 8 2 7 9 5
6 8 4 2 7 1 3 5 9
9 1 2 8 3 5 6 4 7
5 3 7 9 6 4 2 1 8
2 7 9 1 5 8 4 6 3
4 5 8 3 2 6 9 7 1
1 6 3 7 4 9 5 8 2

输出样例:

1
0
0

解题思路:

这道题主要是一个记录是否重复出现的问题,然后我们在输入后,对行,列,宫三者分别进行判断即可。

  1. 读取将要验证的数独解的数量n
  2. 对于每个数独解,读取9x9的矩阵s
  3. 使用矩阵hlg来检查每行、每列和每个宫中的数字是否唯一。
  4. 如果在任何检查中发现重复的数字,将flag设置为0,表示数独解无效。
  5. 输出每个数独解的有效性。

C代码展示:

cpp 复制代码
#include <stdio.h>

int main() {
    int n; // 定义变量n,用于存储将要验证的数独解的数量
    scanf("%d", &n); // 读取数独解的数量

    for (int i = 0; i < n; i++) { // 循环处理每个数独解
        int s[10][10] = {{0}}, h[10][10] = {{0}}, l[10][10] = {{0}}, g[10][10] = {{0}}, flag = 1; // 定义四个9x9的矩阵s、h、l和g,并初始化为0,flag用于标记数独解是否有效

        for (int j = 0; j < 9; j++) { // 读取数独矩阵
            for (int k = 0; k < 9; k++) {
                scanf("%d", &s[j][k]); // 读取数独矩阵的每个元素
                if (s[j][k] > 9 || s[j][k] < 1) flag = 0; // 检查数字是否在1到9之间
            }
        }

        // 行判断
        for (int j = 0; j < 9 && flag == 1; j++) { // 遍历每行
            for (int k = 0; k < 9 && flag == 1; k++) { // 遍历每列
                if (h[j][s[j][k]]) flag = 0; // 检查该数字是否已在当前行出现过
                h[j][s[j][k]] = 1; // 标记该数字在当前行已出现
            }
        }
        // 列判断
        for (int j = 0; j < 9 && flag == 1; j++) { // 遍历每列
            for (int k = 0; k < 9 && flag == 1; k++) { // 遍历每行
                if (l[k][s[j][k]]) flag = 0; // 检查该数字是否已在当前列出现过
                l[k][s[j][k]] = 1; // 标记该数字在当前列已出现
            }
        }
        // 宫判断
        for (int j = 0; j < 9 && flag == 1; j++) { // 遍历每个宫的行
            for (int k = 0; k < 9 && flag == 1; k++) { // 遍历每个宫的列
                int x = j / 3 * 3 + k / 3; // 计算宫的索引
                if (g[x][s[j][k]]) flag = 0; // 检查该数字是否已在当前宫出现过
                g[x][s[j][k]] = 1; // 标记该数字在当前宫已出现
            }
        }

        printf("%d\n", flag); // 输出数独解是否有效(1表示有效,0表示无效)
    }

    return 0;
}
cpp 复制代码
//由于行列宫的判断是基本一致的,所以我们可以同时进行,然后一下是我精炼之后的代码
#include <stdio.h>
#include <string.h>

int main(){
    int n;
    scanf("%d", &n);
    for (int i=0; i<n; i++){
        int flag=1, h[3][10][10]={{{0}}};
        for (int j=1;j<=9;j++){
            for (int k=1;k<=9;k++){
                int x;
                scanf("%d", &x);
                if (x > 9 || x < 1) flag=0;
                else {
                    int g=(j-1)/3*3+(k-1)/3;
                    if (h[0][j][x]||h[1][k][x]||h[2][g][x]) flag=0;
                    else {
                        h[0][j][x]=h[1][k][x]=h[2][g][x]=1;
                    }
                }
            }
        }
        printf("%d\n", flag);
    }
    return 0;
}
相关推荐
KpLn_HJL25 分钟前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
程序员老冯头2 小时前
第十五章 C++ 数组
开发语言·c++·算法
AC使者6 小时前
5820 丰富的周日生活
数据结构·算法
cwj&xyp7 小时前
Python(二)str、list、tuple、dict、set
前端·python·算法
无 证明7 小时前
new 分配空间;引用
数据结构·c++
xiaoshiguang311 小时前
LeetCode:222.完全二叉树节点的数量
算法·leetcode
爱吃西瓜的小菜鸡11 小时前
【C语言】判断回文
c语言·学习·算法
别NULL11 小时前
机试题——疯长的草
数据结构·c++·算法
TT哇11 小时前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
ZSYP-S12 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring