第1节 算法导论
算法的特性
- 输入
- 输出
- 确定性
- 有限性
描述算法的方式
- 自然语言
- 程序代码
- 伪代码
- 流程图
算法题解的一般过程
- 问题描述
- 解题思路
- 算法描述
- 算法实现(包括代码实现、测试用例、运行结果)
- 总结与讨论(时间、空间复杂度、算法的优点与不足 等)
一道简单的例题
写一个对话程序,输入小明的考试分数,告诉他是否及格
问题描述:
输入:一个整数score (0 <= score <= 100), 输出:一个字符串, 描述该分数是否及格
解题思路:
该问题可以直接用分支语句求解,判断 score >= 60 是 true 或者 false 对应输出不同的语句即可
算法描述:
- 输出"请问小明考了多少分?",提示用户输入分数
- 从键盘读入一个整数score
- 判断score是否大于等于60,存到变量isPass里
- 如果isPass为true,屏幕输出“你真厉害!”
- 否则isPass为false,屏幕输出“请再继续努力!”
算法实现:
Java语言实现如下:
public static void main(String[] args) throws Exception {
// 1. 输出"请问小明考了多少分?",提示用户输入分数
System.out.println("请问小明考了多少分?");
// 2. 从键盘读入一个整数score
Scanner scan = new Scanner(System.in);
int score = scan.nextInt();
scan.close();
// 3. 判断score是否大于等于60,存到变量isPass里
boolean isPass = score >= 60;
// 4. 如果isPass为true,屏幕输出“你真厉害!”
if (true == isPass) { // (*1)
System.out.println("你真厉害!");
} else {
// 5. 否则isPass为false,屏幕输出“请再继续努力!”
System.out.println("请再继续努力!");
}
}
总结与讨论:
上面通过完整的解题过程演示了一道简单题的实现,时间复杂度为O(1)
同时提醒我们要理解编程语言的特性,养成良好编码习惯。在本题代码的 (*1)
位置,我们在写==
比较时,应当把常量写在前面,变量写在后面,这样如果我们万一不小心误将 ==
写成 =
时,编译器会编译错误,提醒我们修正代码
第1节 课后思考题
问题描述:
求整数 a
, b
的平均数(a
b
均为 32位 int
,答案向下取整)
解题思路:
题目看似很简单,但如果是在算法面试中遇到,就要留心,是否需要有进一步的考虑
很容易想到一个写法是c = (a + b) / 2
,但是我们来看一个反例:a = 1; b = 2147483647
,如果写代码验证会发现答案变成了一个负数,这是因为计算(a + b)
这个中间过程时,答案超出了32位整数的上限,发生了溢出
有很多种写法可以避免溢出,这里提供两种思路:
方法一:
分类讨论,当a b
同号时使用a + (b - a) / 2
计算,不同号时采用(a + b) / 2
计算
static int getMean(int a, int b) {
if (a < 0 == b < 0) {
return a + (b - a) / 2;
} else {
return (a + b) / 2;
}
}
方法二:
先将a b
各自取一半,然后再相加,但注意由于向下取整的关系,当a b
均为奇数时,会产生1
的误差,需要将这个误差补上
static int getMean(int a, int b) {
int c = a / 2 + b / 2;
if (a % 2 == 1 && b % 2 == 1)
c++;
return c;
}
然后这个代码可以用二进制位运算进一步优化成更简单的形式:
static int getMean(int a, int b) {
return (a >> 1) + (b >> 1) + (a & b & 1);
}