算法分析神奇之时间复杂度、空间复杂度、稳定性

本文深入讲解了算法的时间复杂度和空间复杂度概念,通过具体示例解析了如何计算时间复杂度,并介绍了递归算法的时间复杂度计算方法。此外,文章还探讨了空间复杂度的计算方法及其与算法性能的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法复杂度分为时间复杂度和空间复杂度。其作用: 时间复杂度是指执行算法所需要的计算工作量;而空间复杂度是指执行这个算法所需要的内存空间。(算法的复杂性体现在运行该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度)。
一、时间复杂度

void Test1(int n)
{
    int iConut = 0;
    for(int i = 0; i < n; ++i)
    {
        for(int j = 0; j < n; ++j)
        {
            iCount++;
        }
    }
    for(int k = 0; k < 2*n; ++k)
    {
        iCount++;
    }
    int count = 10;
    while(count--)
    {
        iCount++;
    }
}

计算上述函数的时间复杂度
这里写图片描述

由上面的小栗子我们可以看出,在计算一个算法的时间复杂度之时,其实是在计算语句的执行次数。
时间复杂度实际就是一个函数,该函数计算的是执行基本操作的次数。
算法分析的分类:
1. 最坏情况:任意输入规模的最大运行次数。(上界)
2. 平均情况:任意输入规模的期望运行次数。
3. 最好情况:任意输入规模的最小运行次数,通常最好情况不会出现。(下界)
而在计算一个算法的时间复杂度之时,是在求解一个算法的最坏情况。
下面让我们来了解一些计算时间复杂度的方法
(一)O渐进表示法
一个算法中语句总的执行次数称为语句的频度或时间频度,记为T(n),n称为问题的规模。一般情况下,算法总的执行次数T(n)是问题规模(n)的某个函数f(n),当n不断变化时,时间频度T(n)也会不断的变化,当n趋近于无穷大时,算法执行次数的增长率和f(n)的增长率相同,记作T(n) = O(f(n)),称O(f(n))为算法的时间复杂度。
(二)常见算法的时间复杂度

void Test0(int n) // f(n) = 10===O(10)--->O(1)
{
    int iCount = 0;
    for (int iIdx = 0; iIdx < 10; ++iIdx)
    {
        iCount++;
    }
}

这里写图片描述

void Test1(int n) // f(n) = n+10==>O(2n+10)==>O(n)
{
    int iCount = 0;
    for (int iIdx = 0; iIdx < 10; ++iIdx)
    {
        iCount++;
    }
    for (int iIdx = 0; iIdx < 2*n; ++iIdx)
    {
        iCount++;
    }
}

这里写图片描述

void Test2(int n) // f(n) = n^2 + 2*n + 10===O(f(n))===O(n^2)
{
    int iCount = 0;
    for (int iIdx = 0; iIdx < 10; ++iIdx)
    {
        iCount++;
    }
    for (int iIdx = 0; iIdx < 2*n; ++iIdx)
    {
        iCount++;
    }
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            iCount++;
        }
    }
}

根据上面的分析,我们已经了解到了一个算法的时间复杂度是如何计算出来的,根据上面的方法,因此这个算法的时间复杂度是:f(n)=n^2+2n+10==O(n^2+2n+10)—>O(N^2)

void Test4(int m, int n)// f(n,m) = 2*m*n == O(m*n)
{
    int iCount = 0;
    for (int i = 0; i < 2 * m; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            iCount++;
        }
    }
}

f(n,m)=2*m*n==O(2*m*n)—->O(m*n)

由上面我们可以看出,我们在计算时间复杂度的时候,忽略了一些值,这些值到底是怎么忽略的,在忽略的时候,我们又需要注意什么,下面,我们就来给出准则:
一般算法O(n)计算方法:
1、用常数1取代运行时间中的所有加法常数
2、在修改后的运行次数函数中,只保留最高阶项
3、如果最高阶项系数存在且不是1,则去除与这个项相乘的常数。

有了上面的原则,我们在计算时间复杂度的时候,就更加的得心应手了。
总的来说,一个算法的时间复杂度,就是计算语句的执行次数

下面我们来给出递归算法的时间复杂度
递归算法的时间复杂度为递归总次数*每次递归次数。(即函数调用的次数)

常见的时间复杂度
这里写图片描述
这里写图片描述

二、空间复杂度
一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。
(1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。
S(n)=O(f(n))
其中n为问题的规模,S(n)表示空间复杂度。

空间复杂度的计算跟时间复杂度类似,也使用大O的渐进表示法。–(对象的个数)
要注意的是递归算法的空间复杂度,假如递归深度为N*每次递归的空间大小,如果每次递归的空间为常数,则空间复杂度为O(N)。

总结就是:空间复杂度就是一个算法是否有开辟新的空间,如果有,则为开辟空间的个数

long long Fibonacci1(int n)
{
    return n < 2 ? n : Fibonacci(n - 1) + Fibonacci( n - 2);
}

这里写图片描述

有关空间复杂度的计算,本来就跟空间复杂度有异曲同工之处,因此还希望大家可以注意。

三、稳定性
稳定性一般适用于排序算法中,因为在排序算法中,会涉及到元素的搬移以及交换,因此元素的位置就会发生变化,对于稳定性的理解,将极大程度的让我们理解排序,从而可以给出更优的排序算法。

如果在元素序列中有两个元素R[i]和R[j],它们的排序码K[i] == k[j],且在排序之前,元素R[i]在R[j]的前面。如果在排序之后,元素R[i]仍在R[j]之前,则称这个排序算法是稳定的,否则称这个排序算法是不稳定的。
这里写图片描述

有关算法的时间复杂度,空间复杂度以及稳定性的分析,大概就这么多的内容,希望我们一起进步

只有不停的奔跑,才能不停留在原地!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值