机器学习 | 时间复杂度和空间复杂度

1 前言

在学一些机器学习模型的时候,经常会听到时间复杂度和空间复杂度的概念,内心不禁问一句,这都什么鬼?(黑人问号脸)于是今天小编终于摆脱了懒癌,下定决心查了下相关的资料,终于弄明白了一些!下面和大家分享一下~

2 时间复杂度

2.1 含义

什么叫时间复杂度?简而言之,就是你这段代码执行所需的时间!但是即使是同样的样本在不同的机器上运行时间也可能存在差异,另外你总不能老是让代码先run起来,然后再判断吧?那样效率也太低了,不切实际,需要进行提前判断!因此肯定不能用具体程序运行的时间来表示时间复杂度了,而是要抽象出来!适用于不同的模型!如何抽象呢?简单来说就是程序的运行次数来表示时间复杂度!数学上使用的表示方法则是 大O符号表示法!同时有一点值得注意的是:大O符号表示法并不是用于来真实代表算法的执行时间的,它是用来表示代码执行时间的增长变化趋势的,这个在下面的例子中将体现的会比较好!

2.2 如何求解

三步:

  • 找出算法中的基本语句。算法中执行次数最多的那条语句就是基本语句,通常是最内层循环的循环体。
  • 计算基本语句的执行次数的数量级。只需计算基本语句执行次数的数量级,这就意味着只要保证基本语句执行次数的函数中的最高次幂正确即可(即上面说到的表示趋势!忽略细枝末节!),可以忽略所有低次幂和最高次幂的系数。这样能够简化算法分析,并且使注意力集中在最重要的一点上:增长率。
  • 用大Ο记号表示算法的时间性能。

2.3 具体有哪几种形式?

以下形式中时间复杂度逐步提升!其中1-6称为多项式时间,7-8称为指数时间。多项式时间复杂度的算法是有效算法,称为P(Polynomial,多项式)类问题,而指数时间复杂度的算法称为NP(Non-Deterministic Polynomial, 非确定多项式)问题。

  1. 常数阶O(1)
  2. 对数阶O(logN)
  3. 线性阶O(n)
  4. 线性对数阶O(nlogN)
  5. 平方阶O(n²)
  6. 立方阶O(n³)
  7. K次方阶O(n^k)
  8. 指数阶(2^n)

2.4 如何确定一段代码对应上面哪种形式?

首先来看两个法则:

  • 求和法则。适用于非循环结构。
  • 乘法法则。适用于循环结构。

2.4.1 常数阶O(1)

int i = 1;
int j = 2;
++i;
j++;
int m = i + j;

以上代码就是时间复杂度为O(1),即无论代码执行了多少行,只要是没有循环等复杂结构,那这个代码的时间复杂度就都是O(1)

2.4.2 线性阶O(n)

循环n次,即复杂度为O(n):

for(i=1; i<=n; ++i)
{
   j = i;
   j++;
}

for循环里面的代码会执行n遍,因此它消耗的时间是随着n的变化而变化的,因此这类代码都可以用O(n)来表示它的时间复杂度。

2.4.3 对数阶O(logN)

可能大家会有点奇怪,诶,为啥出现个对数呢?这是因为在一些循环中,并不是就执行N次,而是有条件的终止!具体见:

int i = 1;
while(i<n)
{
    i = i * 2;
}

在while循环里面,每次都将 i 乘以 2,乘完之后,i 距离 n 就越来越近了。那执行多少次能达到n呢?假设循环x次之后,i 就为n 了,此时这个循环就退出了,也就是说 2 的 x 次方等于 n,那么 x = log2^n

也就是说当循环 log2^n 次以后,这个代码就结束了。因此这个代码的时间复杂度为:O(logn)

注:有的地方看到有底数2,有的又没有,应该是一致的!

2.4.4 线性对数阶O(nlogN)

这个就好理解了,适用于乘法法则!在一个while语句外面套一层执行n次的for循环即可!

for(m=1; m<n; m++)
{
    i = 1;
    while(i<n)
    {
        i = i * 2;
    }
}

2.4.5 平方阶O(n²)

这个也比较好理解,n次for循环外面再套一层n次for循环!

for(x=1; i<=n; x++)
{
   for(i=1; i<=n; i++)
    {
       j = i;
       j++;
    }
}

如果将其中一层循环的n改成m,即:

for(x=1; i<=m; x++)
{
   for(i=1; i<=n; i++)
    {
       j = i;
       j++;
    }
}

那么时间复杂度就变成了 O(m×n)

2.4.6 立方阶O(n³)

套3层n次for循环即可!

2.4.7 K次方阶O(n^k)

套k层n次for循环即可!

2.4.8 指数阶(2^n)

套n层2次for循环即可!

3 空间复杂度

3.1 含义

  • 同时间复杂度,空间复杂度也不是用来计算程序实际占用的空间的。
  • 空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势,我们用 S(n) 来定义。
  • 空间复杂度比较常用的有:O(1)、O(n)、O(n²)

3.2 举例

3.2.1 空间复杂度 O(1)

如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)

int i = 1;
int j = 2;
++i;
j++;
int m = i + j;

3.2.2 空间复杂度 O(n)

int[] m = new int[n]
for(i=1; i<=n; ++i)
{
   j = i;
   j++;
}

产生了一个新的数组m,数据占用的大小为n。这段代码的2-6行,虽然有循环,但没有再分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,即 S(n) = O(n)

4 参考

猜你喜欢

转载自blog.csdn.net/qq_27782503/article/details/91423015