您的位置:首页 > 游戏 > 手游 > 宁波外发加工网_申请网站一年多少钱_西安百度竞价外包_seo单词优化

宁波外发加工网_申请网站一年多少钱_西安百度竞价外包_seo单词优化

2024/11/16 13:16:45 来源:https://blog.csdn.net/amos_cloud/article/details/143655548  浏览:    关键词:宁波外发加工网_申请网站一年多少钱_西安百度竞价外包_seo单词优化
宁波外发加工网_申请网站一年多少钱_西安百度竞价外包_seo单词优化

1.1 算法基本概念与复杂度分析

算法是一种解决问题的具体方法。在这一章节中,我们将会了解到算法的基本概念,包括输入、输出、算法正确性、算法复杂度等。我们还将会学习如何分析算法的时间复杂度和空间复杂度,以便在实际应用中选择最优的算法。

什么是算法?

算法是一种解决问题的具体方法。我们可以将生活中的很多问题都看作一个算法。例如,制作一杯咖啡的过程就是一个算法:

  1. 准备一个空杯子。
  2. 将咖啡豆研磨成合适的粒度。
  3. 将咖啡粉放入咖啡机中。
  4. 加入足够的水。
  5. 启动咖啡机。
  6. 等待几分钟,直到咖啡机完成任务。
  7. 将咖啡倒入杯子中。
  8. 按需添加糖或牛奶。
  9. 享受你的咖啡。

这个过程就是一个算法,它有输入(空杯子、咖啡豆、水)、输出(一杯咖啡)、过程(研磨、冲泡)、正确性(研磨成合适的粒度,加入足够的水等)和复杂度(咖啡豆的研磨时间、水的加入量等)。同样,制作一个蛋糕、修理一辆车、打扫房间等都可以看作是一个算法,只是它们的 输入输出过程正确性复杂度 都不同而已。

初识复杂度

复杂度是一个用于衡量算法好坏的参考标准。就像我们评价一个人的诚信度,可以使用芝麻分作为参考一样。

那什么又算是好的算法呢,下面我们来看一张图:

在这里插入图片描述

从图中我们可以看出,蓝色的线随着数据规模的增加,程序运行时间并没有显著增加。而红色的线,随着数据规模增加,运行时间增长的非常快,以至于数据规模到达一定程度,程序的运行时间会变得不可接受。

你可能已经发现了,所谓的复杂度其实就是一个

时间复杂度和空间复杂度

复杂度分析中我们通常会讨论两种复杂度:

  • 时间复杂度:程序的运行时间随数据规模变化的函数。
  • 空间复杂度:程序占用的存储空间随数据规模变化的函数。

复杂度更优的算法,可以起到事半功倍的效果。而复杂度过高的算法,只能停留在理论层面,无法在真实世界中解决工程问题,毕竟如果做一次计算需要一万年,那没人会真正去运行这个程序。

在当今这个时代,计算机的存储成本已经极其低廉,所以我们更侧重关注时间复杂度,有时还会刻意的牺牲空间来换取时间。

复杂度的计算和表示方式

用一台20年前的计算机,和你现在正在用的电脑,运行同一个程序的话,你觉得哪台设备速度更快?显然,这没有可比性。所以复杂度的计算,需要排除硬件和环境的干扰,我们纯粹在理论层面去评判算法的优劣。

可以假设任何计算机的CPU运行一行代码需要使用1个单位时间(Unit Time),记作 1(ut) 。

那么我们看看下面这个函数:

int fun1(int n){return n + 1;
}

核心代码只有一行 return n + 1; ,我们粗略的将其运行时间记作 1(ut),随着输入参数n的变化,函数的运行时间永远都是 1(ut)。

接下来看看这个函数:

int fun2(int n){n /= 2;n = n * n * 3;return n + 5;
}

核心代码有三行 ,我们粗略的将其运行时间记作 3(ut),随着输入参数 n 的变化,函数的运行时间永远都是 3(ut)。

上面的两个例子中的算法,无论输入数据怎么变化,近似的计算时间永远是一个常数,我们把这种算法叫做常数阶。

习惯上我们用一种叫做”大O表示法的形式”,将上面两个程序的时间复杂度记为 O(1) 和 O(3)。

由于任何常数在无穷大面前都可以忽略不计,所以我们在表示常数阶时,一般不会保留具体的数字,而是全部简单的用数字 1 来代替,所以上面两个算法的复杂度都可以写为 O(1)。

下面以Java代码为例,列举常见的各种复杂度的示例算法。

  1. O(1) 常数阶函数:该函数的运行时间与输入规模无关。
public static int constantTime(int x, int y) {return x + y; // 该函数的运行时间不随输入规模而变化
}
  1. O(log n) 对数阶函数:该函数的运行时间随着输入规模的增长而增长,但增长缓慢。
public static int logarithmicTime(int n) {int count = 0;for (int i = 1; i < n; i *= 2) {count++;}return count; // 该函数的运行时间随输入规模的增长而增长,但增长缓慢
}
  1. O(n) 线性阶函数:该函数的运行时间随着输入规模的增长而线性增长。
public static int linearTime(int[] arr) {int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];}return sum; // 该函数的运行时间随输入规模的增长而线性增长
}
  1. O(n log n) 线性对数阶函数:该函数的运行时间随着输入规模的增长略微超过线性增长。
public static int linearithmicTime(int[] arr) {Arrays.sort(arr);int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];}return sum; // 该函数的运行时间随输入规模的增长略微超过线性增长
}
  1. O(n^2) 平方阶函数:该函数的运行时间随着输入规模的增长呈平方级增长。
public static int quadraticTime(int n) {int sum = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {sum++;}}return sum; // 该函数的运行时间随输入规模的增长呈平方级增长
}
  1. O(n^3) 立方阶函数:该函数的运行时间随着输入规模的增长呈立方级增长。
public static int cubicTime(int n) {int sum = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {for (int k = 0; k < n; k++) {sum++;}}}return sum; // 该函数的运行时间随输入规模的增长呈立方级增长
}
  1. O(2^n) 指数阶函数:该函数的运行时间随着输入规模的增长呈指数级增长。
public static int exponentialTime(int n) {if (n <= 0) {return 1;}return exponentialTime(n-1) + exponentialTime(n-2);// 该函数的运行时间随输入规模的增长呈指数级增长
}
  1. O(n!) 阶乘阶函数:该函数的运行时间随着输入规模的增长呈阶乘级增长。
public static int factorialTime(int n) {if (n == 1) {return 1;}return n * factorialTime(n-1);// 该函数的运行时间随输入规模的增长呈阶乘级增长
}
中文名称英文名称复杂度表示描述
常数阶Constant TimeO(1)算法的运行时间不随输入规模而变化
对数阶Logarithmic TimeO(log n)算法的运行时间随输入规模的增长而增长,但增长缓慢
线性阶Linear TimeO(n)算法的运行时间随输入规模的增长而线性增长
线性对数阶Linearithmic TimeO(n log n)算法的运行时间随输入规模的增长而略微超过线性增长
平方阶Quadratic TimeO(n^2)算法的运行时间随输入规模的增长而呈平方级增长
立方阶Cubic TimeO(n^3)算法的运行时间随输入规模的增长而呈立方级增长
指数阶Exponential TimeO(2^n)算法的运行时间随输入规模的增长而呈指数级增长
阶乘阶Factorial TimeO(n!)算法的运行时间随输入规模的增长而呈阶乘级增长

在这里插入图片描述

需要注意的是,对于一个算法,我们考虑他的整体复杂度时,通常只保留最高阶的,而忽略随着数据规模增加,影响可以忽略不计的低阶。

例如,如果有一个算法中既包含常数阶,对数阶又包含平方阶 O(5 + log n + 3*n^2),我们可以直接将其记作 O(n^2)。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com