本来是写给一个女同学看的,没想到会有这么多人看,虽然我已经毕业了,但是我还是维护一下吧。下面放一下我4年来的战果(有点水请见谅

蓝桥杯Java程序设计是叫软件开发吗 蓝桥杯java看什么书_算法


大一到大三从未系统学过算法类课程,零散的看了一下算法书籍,浅学了一些树,图,和其他杂七杂八的算法。直到大四开始看《算法设计与分析基础第3版》(这里强烈推荐,不可多得的好书,能帮你梳理你零散的算法成体系)。我花了半个月看完,并且在看的过程中刷HDOJ的集训题目(现在好像非本校不让进了 )。累加花费一个月左右时间,感觉解题思路一下子清晰明亮。

然后半个月后省赛(轻松拿了省一第4顺位 ),如果顺着这个势头下去估计是拿国一无压力的吧(实际上离国一差了就10个名次,就是自己太菜了 几乎是裸考,因为要毕业了准备论文,准备找工作,太忙了

先在这里给大家推荐几本算法书吧:
《算法设计与分析基础第3版》- 帮你梳理你的算法知识体系,授人以渔
《算法4》- 开拓你的算法思想,不可多得的算法书,难度坡度较大(本人通读过一遍,里面有一些高阶的算法非常实用)
《数据结构基础 - 王道》 - 虽然是考研用的书籍和视频,但是能帮你打下扎实的基础(我大四看过一遍,感觉基础变牢固很多)

赠送一句心得:脚踏实地,一个算法一个算法实践,刷题,总结,对比,看似是最慢的,其实是最快的。

开始吧:从最基础

蓝桥杯最新的参赛选手训练系统,大家可以上去刷题来进行实践。有很多学校自己组织有培训,但是蓝桥杯的比赛环境或许会有不同,在比赛前熟悉一下环境是不是能跑通自己的代码也是很重要的!!!

比赛开始前:
一般比赛的文件会加密,然后比赛开始的时候老师会发一个密码给大家。文件开头有当前参数选手需要注意的,一定要看!!!这里会介绍你的参赛环境相关的注意事项。

类似比如:
Java: 你的类名必须是Main,并且不能有package语句。
C/C++:你的main函数返回值必须是0,也就是return 0;

下面虽然是C/C++语言描述的,但对于java来说其实同样实用(毕竟两个语言在很多方面很像,而且算法不考语法)。

代码模板 c/c++

比如输入啥的, 那好吧,就输入了。(简单放一点在这里)。
但是在输入之前, 先列举以下写代码的框架。(很low反正你们都知道qwq

// 这是写代码的模板, 请你开始写代码第一件事就是将下面写出来
#include<stdio.h>
#include<bits/stdc++.h>// 万能头文件, 蓝桥杯是支持的。可以用。
// 这里添加变量
// 这里后面可以添加函数
int main(){
	// 这里写代码。。。。。
	return 0;// 注意要return 0;
}

我在评论区看到了如下评论:
A :会增加代码运行时间(编译时长),蓝桥杯代码大题有时长要求慎用
我的回答:
其实这个评论很严谨,确实是可能有一点点,我没有验证过,官方也没提到,如果你在意就背头文件好了(反正我背不住

好了开始输入

对于输入来说 比如题目 :

第一行输入一个数 N ,接下来一行 ( 或者 N 行,每行一个数字 ) 。
接下来是数据范围(题目会给,一般在题目最后, 题目中或许会隐含有范围要注意)。
对于10%的数据 0 <= N <= 100 对于30%的数据 0 <= N <= 1000 对于100%的数据 0 <= N <= 50000 在处理输入前一定要看数据范围!!!非常重要,重要!!!!!!

那么 请仔细看 注释注释
下面开始正式写代码。

#include<bits/stdc++.h>
int MAX = 50005;// 这里是50000 + 5  也就是100%的数据范围 + 5, 定义在这里
int N = 0; // 这样的数据定义为全局变量方便使用。
int num[MAX] = {};// 定义一个数组存放数据  
// 用MAX做为数组长度
// = {};  是初始化数组数据为0;
int main(){
	// 对于输入一律用scanf, 不管是字符串还是啥。(~~当然还有快读,但是蓝桥杯用不到~~ )
	scanf("%d", &N);// 输入N ~~记得取址符号~~ 
	for(int i = 0; i < N; ++i){// 最简单的循环
		scanf("%d", num + i);// 输入N行数据
	}// 输入结束
	return 0;// 注意要return 0;
}

进阶技巧:

数据范围隐含了当前题目需要用到算法的时间复杂度,比如[0,10000]内的可以使用时间复杂度为N^2的算法,[0,100000]使用N * logN,再往上一般是[0 <= N <= 100000000],只能用N,再往上就是logN了(蓝桥杯没有,我就没见过

题目时间限制表示你当前程序执行如果超过这个时间就会被判超时,如果一个数据点超时就是0分(蓝桥杯一般会有10个数据点,从低数据量到高数据量执行,数据量越高得分越多),这个时间范围不会影响到你决策算法时间复杂度,这个一般是用来平衡当前题目的常数值,也就是C * N的算法可以通过,这个C是一个常数,也就是如果你在代码级别上优化好了才可以通过。给你加了一个C值一般是因为题目复杂需要进行平衡,或者放宽了要求。

骗分技巧:(不知道蓝桥杯官网看到了会不会打我

如果你实在不会做,题目不是有输入样例和输出样例吗!我们可以在做不出来的情况下,或者时间不够的情况下将输入样例固定输出。
比如:
if 输入 == 3,输出10
if 输入 == 4,输出20
这里可以拿到样例数据点的分数,(不知道蓝桥杯改了没有

输出:

这里接着上面的题目写。
题目:

你需要输出这 N 个数的逆序对的个数。(就是输出一个数)。
接着上面的程序继续。

#include<bits/stdc++.h>
int MAX = 50005; 
int N = 0;  
int num[MAX] = {}; 

/
int answer = 0;// 根据题目要求新增一个变量, 用来记录答案,
// 如果答案是一串数字需要用数组。
/
 
int main(){
	scanf("%d", &N); 
	for(int i = 0; i < N; ++i){ 
		scanf("%d", num + i); 
	}// 输入结束
	
	// 假设你已经计算完结果

	// 那么这里可以开始输出
	printf("%d\n", answer);// 注意格式(格式不对可能没分),后面一般要跟一个换行符, 就是输出最后一行后要换行。 
	
	return 0; 
}

杂项

主函数return 0; 一定记得!
输入/出 long long数据需要使用的是

long long x = 0;
scanf("%I64d", &x);
printf("%I64d", x);

对于数组来说, 静态申请的一维数组最大长度大概为:

int num[500000000]; // int 可申请5*10的8次方左右
long long num[200000000]; // long long 可申请2*10的8次方左右

:蓝桥杯最大栈空间为256MB,经过换算, 你最大可以开 1 * 10的7次方左右的数组空间。也就是1千万。如下:

蓝桥杯Java程序设计是叫软件开发吗 蓝桥杯java看什么书_蓝桥杯Java程序设计是叫软件开发吗_02

数据的范围
需要根据不同的取值范围,确定使用不同的数据类型。当超过20位的数据就要考虑其余的解法,或者自己写大数的运算了(这是我最不想遇到的)。

unsigned int 0~4294967295 // 9及以下位数都可装
int -2147483648~2147483647 // 9及以下位数都可装
unsigned long 0~4294967295 // 9及以下位数都可装
long -2147483648~2147483647 // 9及以下位数都可装
long long的最大值:9223372036854775807 // 18及以下位数都可装 19位也差不多
long long的最小值:-9223372036854775808 // 18及以下位数都可装 19位也差不多
unsigned long long的最大值:18446744073709551615 //20位
// 下面用的可能没有接触过, 但存在, 有上面的就够了, 下面和上面的long long 是一样的。
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615

下面是官网截图:

蓝桥杯Java程序设计是叫软件开发吗 蓝桥杯java看什么书_蓝桥杯参赛_03


当然还有蓝桥杯的最大栈空间是256MB。下面为截图。

蓝桥杯Java程序设计是叫软件开发吗 蓝桥杯java看什么书_蓝桥杯备赛基础_04

一些简单的优化问题 * 不涉及算法(可能大家都知道)

  1. 当需要多次使用一个表达式的值的时候, 可以存起来。 这样可以减少计算次数。
int n = 10;
int b = 30;
for(int i = 0; i < n; i++){
	printf("%d", n * b * i);
}

还有就是,计算一个数组 / 或者字符串长度的时候, 最后一直存着,以免多次计算。

// 更改为
int n  = 10;
int b = 30;
int t = n * b;
for(int i = 0; i < n; i++){
	printf("%d", t * i);
}
  1. 多使用位运算
// 如:
int n = 30;
int i =  n* 2;
int c =  n / 16;
// 可以更改为
int i = n << 1; // 相信我会快。
int c =  n >> 4;

如:

int i = 100;
while(i % 2 == 1){// 对于for循环同样使用。
	i--;
}
// 改为
while(i & 1){ // 用位运算代替
--i;// 前自减/增 比 后自减/增快。
}

如:

int i = 0;
int x = i--;
// 改为
int x = i;
--i;// 这样结果一样, 但编译后,会少一条汇编指令。