读《剑指offer》有感
前言
今天写《数据结构笔记1(绪论及其理解)》的时候,写到算法的评价标准,然后想起之前好像写过类似的笔记,在电脑上找了一下,还真找到了。
笔记
原笔记
读《剑指offer》有感5月14日写
编程语言只是一种工具,重要的是思想。——引用自某个博客的话。挺有共鸣的 。
虽然5/8收到了这本书,在此之前也找到过这本书的PDF,但是看电子书和看纸质书的感觉完全不一样。把纸质书拿着手中更加具体,对书的厚度有直观的感受。
我觉得这本书的精华在于作者说的应聘者需要具备的五个素质。
1扎实的基础知识:编程语言、数据结构、算法
2高质量的代码:规范性、完整性、健壮性
3清晰的思路:画图、举例、分解
4优化效率的能力:学会优化时间效率以及用空间换时间的常用算法
5其余能力:学习能力和沟通能力、举一反三、抽象建模、发散思维的能力。
至于面不面试都是次要的。
最重要的是前三点,不管编程还是做事,这三点都很有作用。
一、扎实的基础
编程语言:赋值运算符函数、实现单例模式。
数据结构:数组、字符串、链表、树、栈和队列
算法和数据操作:递归和循环、查找和排序、回溯法、动态规划与贪婪算法、位运算。
二、高质量的代码
规范性:清晰的书写、清晰的布局、合理的命名
完整性:功能测试、边界测试(处理边界值测试案例)、负面测试(处理错误输出)
健壮性:容错性
三、清晰的思路
画图:使抽象问题形象化
举例:使抽象问题具体化
分解:是复杂问题简单化
补充笔记
重要的不光前三点。
首先明白编程是什么。
我觉得编程就是编写程序,程序是算法的实现。程序是一套处理框架。在计算机中的体现是输入数据,处理数据,最终输出想要的结果。
程序常常和数学相关,其实就是数学的计算步骤可以很好地让机器理解,进而实现。比如一开始的计算,后来的图像处理,再到互联网的文档处理。现在语言的逻辑步骤也能让机器处理。
因为随着计算机的发展,语言也慢慢可以被计算机处理,常见的应用就是自然语言处理、关键词搜索、敏感词过滤。这些功能的实现就是一个一个程序的组合,宏观上看就是输入数据,处理数据,最后输出数据。
最终万物皆可编程。编程就是用计算机语言编写一套处理框架。这套处理框架可以代替人的重复操作。比如爬虫其实就是请求网页、收集信息;
然后明白编程的实现原理
编程有三大基本功,分别是数据结构、算法、设计模式。不过在这三大基本功的背后还有操作系统、计算机组成原理的底层概念。如硬件中的存储、计算是如何实现的,软件的进程调度、内存管理(请求分页式管理、置换算法)。
其实编程的基本功,是一些成熟的算法。用这些成熟的算法其实可以处理现实中绝大多数的事情。
接着明白算法是什么
算法其实就是处理步骤的描述。算法其实有许多分类,比如操作系统中的进程调度就是算法、内存的置换算法也是算法。
面对不同现实问题将其转化成数据结构,然后通过处理这些数据结构来解决现实问题,其中处理数据结构的操作步骤也是算法。
还有就是设计模式。设计模式是解决软件设计中常见问题的可复用方案。这个方案就是算法。
处理图像的步骤也是算法,爬虫的操作过程也是算法。
算法就是步骤的描述。
编程就是将这个描述用到计算机中,通过编程,最终实现程序。程序代替我们进行这些步骤。
编程思想
明白算法后,就要明白算法的评价标准
正确性。代码首先需要正确实现基本功能。通常通过功能测试、边界测试、负面测试三个方面。
可读性。主要是规范化。实现规范化虽然在第一次开发的时候会比较繁琐,但是便于二次开发;有助于代码的成长;规范性注意通过代码布局、规范命名两个部分去提升。在前端有专业的代码格式化插件,可以帮助提高代码的可读性;2020最新版vscode格式化代码;
健壮性。主要是输入的处理。正常是指程序能够判断输入十分合乎规范要求,并对不规范要求的输入给予合理处理。其实就是编程的异常处理。除了输入的异常处理,其实还有死循环的处理。这两部分确保代码的健壮性。健壮性其实和正确性有一定关联。
节约时间与空间。其实和经济学面临的问题很相似,都是对稀缺资源进行资源配置。为了衡量节约时间与空间的程度,计算机科学家定义了时间复杂度与空间复杂度。面对同样的问题,不同的算法会带来不同的时间复杂度,而不同的时间复杂度会带来的不同的响应时间。我们自然希望结果快点出来。所以优化代码的时间复杂度很有必要。优化时间复杂度的小知识有很多,我这里就不展开了,可以百度。除了时间的优化,还有空间的优化,不过由于摩尔规律,硬件的提升迅速,空间的优化没有时间的优化那么要紧,常常使用以空间换时间。
这个评判标准其实参考了许多方面。用管理学的角度说。就是有不同计划(数据结构、设计模式),根据不同情况做出对应决策(时间与空间的取舍),接着实施,在实施的过程中做好控制(正确性、健壮性)和沟通(可读性)。
上面的主要还是在个人角度看。其实还有从整个软件的角度看。软件工程就是研究团队编程的学科。
软件危机:“已完成”的软件,不满足用户的需求,进度不能保障,开发成本难测;质量没有保证。
其实和管理的问题一样。
软件工程的定义是:将系统化的、规范的、可度量的方法应用于软件的开发、运行和维护过程,以及对所选方法的研究。
和管理学的定义一样。
软件生命周期:1可行性研究、2需求分析、3设计、4编码、5测试、集成、维护阶段。6.软件
前三部分和管理学的计划设计一样。需求分析(分析目的)、可行性分析(分析可行性)、设计;
- 可行性研究的目的是:用最小的代价在尽可能短的时间内确定问题是否能够解决。
- 可行性研究的四大要素是:经济上可行,技术可行,法律允许、社会环境可行。
其实就是PEST分析
需求工程是指应用有效的技术和方法进行需求分析,确定客户需求,帮助分析人员理解问题,定义目标系统的外部特征的一门学科。需求工程中的主要活动有:需求获取、需求分析、需求规格说明、需求验证和需求变更管理。
其实和激励相关
软件设计的主要原则:模块独立性和信息隐藏。反映模块独立性有两个标准:内聚和耦合。内聚衡量一个模块内部各个元素彼此结合的紧密程度,耦合衡量模块之间彼此依赖的程度。
和组织设计相关
软件测试的定义:是为了发现错误而执行程序的过程,其目的在于以最少的时间和人力,系统地找出软件中潜在的各种错误和缺陷。
和控制相关
举个例子(斐波那契数列)
题目描述:
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。
n<=39
问题分析:
可以肯定的是这一题通过递归的方式是肯定能做出来,但是这样会有一个很大的问题,那就是递归大量的重复计算会导致内存溢出。另外可以使用迭代法,用fn1和fn2保存计算过程中的结果,并复用起来。下面我会把两个方法示例代码都给出来并给出两个方法的运行时间对比。
示例代码:
采用迭代法:
int Fibonacci(int number) {
if (number <= 0) {
return 0;
}
if (number == 1 || number == 2) {
return 1;
}
int first = 1, second = 1, third = 0;
for (int i = 3; i <= number; i++) {
third = first + second;
first = second;
second = third;
}
return third;
}
采用递归:
public int Fibonacci(int n) {
if (n <= 0) {
return 0;
}
if (n == 1||n==2) {
return 1;
}
return Fibonacci(n - 2) + Fibonacci(n - 1);
}
从这例子中,我们可以看到不同的算法会带来不同的时间复杂度(响应时间)和空间复杂度(空间占用)。
同样实现一个功能,好的算法响应更快,占的空间更小。
数据结构就是现成的算法,设计模式也是现成的算法。掌握这些算法,并且灵活使用,可以将现实中的操作步骤迁移到计算机中。
- 学习能力和沟通能力
- 举一反三
- 抽象建模
- 发散思维的能力。
总结
写到最后,发现话题太多了,不太好面面俱到。所以暂时写到这。
大家可以看看架构师如何进行编程语言的挑选(性能与简便性)、团队的代码规范(可读性)、性能优化(时间复杂度、空间复杂度)、工程思想等等。
更新地址:GitHub