1 算法的基本概念
1.1 算法是什么?
算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每条序列指令表示一个或多个操作。
举例:程序 = 数据结构(要处理的信息) + 算法(处理信息的步骤);在这个例子中,食材代表数据结构,做菜步骤代表的就是算法了
1.2 算法的特性
- 有穷性:一个算法必须总在执行有穷步之后结束,且每一步都可在有穷时间内完成。(算法必须有穷,程序可以无穷)
- 确定性:算法中每条指令必须有确切的含义,对于相同的输入只能得到相同的输出。(不可有歧义)
- 可行性:算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。(不可以天马行空)
- 输入:一个算法有0个或者多个输入,这些输入取自某个特定的对象的集合。
- 输出:一个算法要有0个或者多个输出,这些输出与输入有着某种特定关系的量。
一个算法必须具备以上5个特性!
1.3 好算法的特点
- 正确性:算法应能够正确地解决求解问题。(一个好算法最基本的应该能正确解决问题吧!)
- 可读性:算法应具备良好的可读性,以帮助别人理解。(一个好算法最起码可以让别人轻易读懂吧!)
- 健壮性:输入非法数据时,算法能适当的做出反应或进行处理,而不会产生莫名奇妙的输出结果
- 效率与低存储量需求:效率是算法执行的时间,储存量需求是指算法执行过程中所需要的最大存储空间,这两者都与问题的规模有关。(怎么才可以从众多算法中脱颖而出,就看时间复杂度跟空间复杂度啦)
2 算法的时间复杂度
2.1 什么是时间复杂度
2.1.1 频度
一个语句的频度是指该语句在算法中被重复执行的次数。算法中所有语句的频度之和记为T(n),它是该算法问题规模n的函数,时间复杂度主要分析的就是T(n)的数量级。
2.1.2 时间复杂度
通常采用算法中的基本运算的频度来分析算法的时间复杂度,因此算法的时间复杂度记为 T(n) = O(f(n))
问题1:为什么只看表达式最高阶的?忽略掉了表达式的其他部分呢?
答:在分析算法的时间复杂度时,我们通常只关注最高阶的项,忽略其他低阶项和常数系数。这是因为随着输入规模增加,最高阶项的影响会远远超过其他项。
问题2:顺序执行的代码,可以忽略吗?
答: 可以,顺序执行的代码仅仅影响常数项,我们只需要挑循环的一个基本操作分析它的执行次数与n的关系即可,如果有多层循环,只需要考虑最深层次的。
2.1.2 计算规则
-
加法规则:多项相加,只保留最高阶的项,且系数变为1
-
乘法规则:多项相乘,都保留。
-
常见的渐进时间复杂度
2.2 最好、最坏、平均时间复杂度
- 最好时间复杂度:在最好情况下,算法的时间复杂度(不重要)
- 最坏时间复杂度:在最坏情况下,算法的时间复杂度(重要)
- 平均时间复杂度:所有可能输入实例在等概率出现的情况下,算法的期望时间(重要)
举例:
#include <iostream>
#include <vector>
int linearSearch(std::vector<int> arr, int target) {
for (int i = 0; i < arr.size(); i++) {
if (arr[i] == target) {
return i; // 返回目标元素在向量中的索引
}
}
return -1; // 目标元素不存在于向量中
}
int main() {
std::vector<int> arr = {5, 2, 9, 1, 7};
int target = 9;
int result = linearSearch(arr, target);
if (result != -1) {
std::cout << "目标元素 " << target << " 在向量中的索引为 " << result << std::endl;
} else {
std::cout << "目标元素 " << target << " 不存在于向量中" << std::endl;
}
return 0;
}
对于这个程序,最好的情况就是搜索的元素在数组的第一个位置–T(n)=O(1);
最坏的情况就是搜索的元素在数组的最后一个位置–T(n)=O(n);
平均情况就是搜索的元素在数组的任意位置的概率相同为1/n–T(n)=O(n);
3 算法的空间复杂度(内存空间与问题规模的关系)
- 算法的空间复杂度S(n)定义为该算法所耗费的存储空间,它是问题规模n的函数。记为:S(n)=O(g(n)),
- 一个程序在执行时除了需要存储空间来存放本身所用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为实现计算所需信息的辅助空间。若输入数据所占空间仅仅取决于问题本身,和算法无关,则只需分析除了输入和程序之外的额外空间
- 算法原地工作:算法所需辅助空间为常量,O(1) (就是说存储空间与问题规模n没关系