Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >[最全算法总结]我是如何将递归算法的复杂度优化到O(1)的

[最全算法总结]我是如何将递归算法的复杂度优化到O(1)的

作者头像
Angel_Kitty
发布于 2019-07-17 14:07:22
发布于 2019-07-17 14:07:22
1.6K00
代码可运行
举报
运行总次数:0
代码可运行

相信提到斐波那契数列,大家都不陌生,这个是在我们学习 C/C++ 的过程中必然会接触到的一个问题,而作为一个经典的求解模型,我们怎么能少的了去研究这个模型呢?笔者在不断地学习和思考过程中,发现了这类经典模型竟然有如此多的有意思的求解算法,能让这个经典问题的时间复杂度降低到 \(O(1)\) ,下面我想对这个经典问题的求解做一个较为深入的剖析,请听我娓娓道来。

我们可以用如下递推公式来表示斐波那契数列 \(F\) 的第​ \(n\) 项: \[ F(n) = \begin{cases} 0, & n = 0 \\ 1, & n = 1 \\ F(n-1) + F(n-2), & n > 1 \end{cases} \] 回顾一下我们刚开始学 \(C\) 语言的时候,讲到函数递归那节,老师总是喜欢那这个例子来说。

斐波那契数列就是像蜗牛的壳一样,越深入其中,越能发觉其中的奥秘,形成一条条优美的数学曲线,就像这样:

递归在数学与计算机科学中,是指在函数的定义中使用函数自身的方法,可能有些人会把递归和循环弄混淆,我觉得务必要把这一点区分清楚才行。

递归查找

举个例子,给你一把钥匙,你站在门前面,问你用这把钥匙能打开几扇门。

递归:你打开面前这扇门,看到屋里面还有一扇门(这门可能跟前面打开的门一样大小,也可能门小了些),你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开。若干次之后,你打开面前一扇门,发现只有一间屋子,没有门了。 你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你可以回答出你到底用这钥匙开了几扇门。

循环:你打开面前这扇门,看到屋里面还有一扇门,(这门可能跟前面打开的门一样大小,也可能门小了些),你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,(前面门如果一样,这门也是一样,第二扇门如果相比第一扇门变小了,这扇门也比第二扇门变小了),你继续打开这扇门,一直这样走下去。 入口处的人始终等不到你回去告诉他答案。

简单来说,递归就是有去有回,循环就是有去无回

我们可以用如下图来表示程序中循环调用的过程:

于是我们可以用递归查找的方式去实现上述这一过程。

时间复杂度:\(O(2^n)\) 空间复杂度:\(O(1)\)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
递归实现
*/
int Fibonacci_Re(int num){
    if(num == 0){
        return 0;
    }
    else if(num == 1){
        return 1;
    }
    else{
        return Fibonacci_Re(num - 1) + Fibonacci_Re(num - 2);
    }
}

线性递归查找

It's amazing!!!如此高的时间复杂度,我们定然是不会满意的,该算法有巨大的改进空间。我们是否可以在某种意义下对这个递归过程进行改进,来优化这个时间复杂度。还是从上面这个开门的例子来讲,我们经历了顺路打开门和原路返回数门这两个过程,我们是不是可以考虑在边开门的过程中边数我们一路开门的数量呢?这对时间代价上会带来极大的改进,那我们想想看该怎么办呢?

为消除递归算法中重复的递归实例,在各子问题求解之后,及时记录下其对应的解答。比如可以从原问题出发自顶向下,每当遇到一个子问题,都首先查验它是否已经计算过,以此通过直接调阅纪录获得解答,从而避免重新计算。也可以从递归基出发,自底而上递推的得出各子问题的解,直至最终原问题的解。前者即为所谓的制表或记忆策略,后者即为所谓的动态规划策略。

为应用上述的制表策略,我们可以从改造 \(Fibonacci\) 数的递归定义入手。我们考虑转换成如下的递归函数,即可计算一对相邻的Fibonacci数:

\((Fibonacci \_ Re(k-1),Fibonacci \_ Re(k-1))\),得到如下更高效率的线性递归算法。

时间复杂度:$ O(n) $ 空间复杂度:$ O(n) $

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
线性递归实现
*/
int Fibonacci_Re(int num, int& prev){
    if(num == 0){
        prev = 1;
    return 0;
    }
    else{
    int prevPrev;
    prev = Fibonacci_Re(num - 1, prevPrev);
        return prevPrev + prev;
    }
}

该算法呈线性递归模式,递归的深度线性正比于输入 \(num\) ,前后共计仅出现 \(O(n)\) 个实例,累计耗时不超过 \(O(n)\)。遗憾的是,该算法共需要使用 \(O(n)\) 规模的附加空间。如何进一步改进呢?

减而治之

若将以上逐层返回的过程,等效地视作从递归基出发,按规模自小而大求解各子问题的过程,即可采用动态规划的过程。我们完全可以考虑通过增加变量的方式代替递归操作,牺牲少量的空间代价换取时间效率的大幅度提升,于是我们就有了如下的改进方式,通过中间变量保存 \(F(n-1)\) 和 \(F(n-2)\),利用元素的交换我们可以实现上述等价的一个过程。此时在空间上,我们由 \(O(1)\) 变成了 \(O(4)\),由于申请的空间数量仍为常数个,我们可以近似的认为空间效率仍为 \(O(1)\)。

时间复杂度:\(O(n)\) 空间复杂度:\(O(1)\)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
非递归实现(减而治之1)
*/
int Fibonacci_No_Re(int num){
    if(num == 0){
        return 0;
    }
    else if(num == 1){
        return 1;
    }
    else{
        int a = 0;
        int b = 1;
        int c = 1;
        while(num > 2){
            a = b;
            b = c;
            c = a + b;
            num--;
        }
        return c;
    }
}

我们甚至还可以对变量的数量进行优化,将 \(O(4)\) 变成了 \(O(3)\),减少一个单位空间的浪费,我们可以实现如下这一过程:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
非递归实现(减而治之2)
*/
int Fibonacci_No_Re(int num){
    int a = 1;
  int b = 0;
  while(0 < num--){
    b += a;
    a = b - a;
  }
  return b;
}

分而治之(二分查找)

而当我们面对输入相对较为庞大的数据时,每每感慨于头绪纷杂而无从下手的你,不妨先从孙子的名言中获取灵感——“凡治众如治寡,分数是也”。是的,解决此类问题的最有效方法之一,就是将其分解为若干规模更小的子问题,再通过递归机制分别求解。这种分解持续进行,直到子问题规模缩减至平凡情况,这也就是所谓的分而治之策略。

与减而治之策略一样,这里也要求对原问题重新表述,以保证子问题与原问题在接口形式上的一致。既然每一递归实例都可能做多次递归,故称作为多路递归。我们通常都是将原问题一分为二,故称作为二分递归。

按照二分递归的模式,我们可以再次求和斐波那契求和问题。

时间复杂度:$O(log(n)) $ 空间复杂度:$ O(1) $​

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
二分查找(递归实现)
*/
int binary_find(int arr[], int num, int arr_size, int left, int right){
    assert(arr);
    int mid = (left + right) / 2;
    if(left <= right){
        if(num < arr[mid]){
            binary_find(arr, num, arr_size, left, mid - 1);
        }
        else if(num > arr[mid]){
            binary_find(arr, num, arr_size, mid + 1, right);
        }
        else{
            return mid;
        }
    }
}

当然我们也可以不采用递归模式,按照上面的思路,仍采用分而治之的模式进行求解。

时间复杂度:$ O(log(n)) $ 空间复杂度:$ O(1) $

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
二分查找(非递归实现)
*/
int binary_find(int arr[], int num, int arr_size){
    if(num == 0){
        return 0;
    }
    else if(num == 1){
        return 1;
    }
    int left = 0;
    int right = arr_size - 1;
    while(left <= right){
        int mid = (left + right) >> 1;
        if(num > arr[mid]){
            left = mid + 1;
        }
        else if(num < arr[mid]){
            right = mid - 1;
        }
        else{
            return mid;
        }
    }
    return -1;
}

矩阵快速幂

为了正确高效的计算斐波那契数列,我们首先需要了解以下这个矩阵等式: \[ \left[ \begin{matrix} F_{n+1} & F_n\\ F_n & F_{n-1} \end{matrix} \right] = \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right] \] 为了推导出这个等式,我们首先有: \[ \left[ \begin{matrix} F_{n+1} \\ F_n \end{matrix} \right] = \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right] \left[ \begin{matrix} F_{n} \\ F_{n-1} \end{matrix} \right] \] 随即得到: \[ \left[ \begin{matrix} F_{n+1} \\ F_n \end{matrix} \right] = \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right]^n \left[ \begin{matrix} F_{1} \\ F_{0} \end{matrix} \right] \] 同理可得: \[ \left[ \begin{matrix} F_{n} \\ F_{n-1} \end{matrix} \right] = \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right]^{n-1} \left[ \begin{matrix} F_{1} \\ F_{0} \end{matrix} \right] = \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right]^{n} \left[ \begin{matrix} F_{0} \\ F_{-1} \end{matrix} \right] \] 所以: \[ \left[ \begin{matrix} F_{n+1} & F_n\\ F_{n} & F_{n-1} \end{matrix} \right] = \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right]^n \left[ \begin{matrix} F_{1} & F_{0}\\ F_{0} & F_{-1} \end{matrix} \right] \] 又由于\(F(1) = 1\),\(F(0) = 0\),\(F(-1) = 1\),则我们得到了开始给出的矩阵等式。当然,我们也可以通过数学归纳法来证明这个矩阵等式。等式中的矩阵 \[ \left[ \begin{matrix} 1 & 1\\ 1 & 0 \end{matrix} \right] \] 被称为斐波那契数列的 \(Q\)- 矩阵。

通过 \(Q\)- 矩阵,我们可以利用如下公式进行计算​ \(F_n\): \[ F_n = (Q^{n-1})_{1,1} \] 如此一来,计算斐波那契数列的问题就转化为了求 \(Q\) 的 \(n-1\) 次幂的问题。我们使用矩阵快速幂的方法来达到 \(O(log(n))\) 的复杂度。借助分治的思想,快速幂采用以下公式进行计算: \[ A^n = \begin{cases} A(A^2)^{\frac{n-1}{2}}, & if \ n \ is \ odd \\ (A^2)^{\frac{n}{2}}, & if \ n \ is \ even \end{cases} \] 实现过程如下:

时间复杂度:\(O(log(n))\) 空间复杂度:\(O(1)\)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//矩阵数据结构定义
#define MOD 100000
struct matrix{
    int a[2][2];
}

//矩阵相乘函数的实现
matrix mul_matrix{
    matrix res;
    memset(res.a, 0, sizeof(res.a));
    for(int i = 0; i < 2; i++){
        for(int j = 0; i < 2; j++){
            for(int k = 0; k < 2; k++){
                res.a[i][j] += x.a[i][k] * y.a[k][j];
                res.a[i][j] %= MOD;
            }
        }
    }
    return res;
}

int pow(int n)
{
    matrix base, res;
    //将res初始化为单位矩阵
    for(int i = 0; i < 2; i++){
        res.a[i][i] = 1;
    }
    //给base矩阵赋予初值
    base.a[0][0] = 1;
    base.a[0][1] = 1;
    base.a[1][0] = 1;
    base.a[1][1] = 0;
    while(n > 0)
    {
        if(n % 2 == 1){
            res *= base;
        }

        base *= base;
        n >>= 1;//n = n / 2;
    }
    return res.a[0][1];//或者a[1][0]
}

对于斐波那契数列,我们还有以下这样的递推公式: \[ F_{2n - 1} = F_n^{2} + F_{n-1}^2 \]

\[ F_{2n} = (2F_{n-1} + F_n) \cdot F_n \]

为了得到以上递归式,我们依然需要利用 \(Q\)- 矩阵。由于 $ Q^m Q^n = Q^{m+n} $,展开得到: \[ F_mF_n + F_{m-1}F_{n-1} = F_{m+n-1} \] 将该式中 \(n\) 替换为 \(n+1\) 可得: \[ F_mF_{n+1} + F_{m-1}F_{n} = F_{m+n} \] 在如上两个等式中令 \(m=n\),则可得到开头所述递推公式。利用这个新的递归公式,我们计算斐波那契数列的复杂度也为 \(O(log(n))\),并且实现起来比矩阵的方法简单一些:

时间复杂度:\(O(log(n))\) 空间复杂度:\(O(1)\)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int Fibonacci_recursion_fast(int num){
    if(num == 0){
        return 0;
    }
    else if(num == 1){
        return 1;
    }
    else{
        int k = num % 2 ? (num + 1) / 2 : num / 2;
        int fib_k = Fibonacci_recursion_fast(k);
        int fib_k_1 = Fibonacci_recursion_fast(k - 1);
        return num % 2 ? power(fib_k, 2) + power(fib_k_1, 2) : (2 * fib_k_1 + fib_k) * fib_k;
    }
}

公式法

我们还有没有更快的方法呢?对于斐波那契数列这个常见的递推数列,其第 \(n\) 项的值的通项公式如下: \[ a_n = \dfrac{(\dfrac{1+\sqrt{5}}{2})^n - (\dfrac{1-\sqrt{5}}{2})^n}{\sqrt{5}}, (n> = 0) \] 既然作为工科生,那肯定要用一些工科生的做法来证明这个公式呀,嘿嘿,下面开始我的表演~

我们回想一下,斐波那契数列的所有的值可以看成在数轴上的一个个离散分布的点的集合,学过数字信号处理或者自动控制原理的同学,这个时候,我们很容易想到用Z变换来求解该类问题。

\(Z\) 变换常用的规则表如下:

当 \(n>1\) 时,由 \(f(n) = f(n-1) + f(n-2)\) (这里我们用小写的 \(f\) 来区分):

由于 \(n >= 0\),所以我们可以把其表示为\(f(n+2) = f(n+1) + f(n)\),其中 \(n >= 0\)。

所以我们利用上式前向差分方程,两边取 \(Z\) 变换可得: \[ \sum_{n=-\infty}^{+\infty}f(n+2) \cdot Z^{-n} = \dfrac{\sum_{n=-2}^{+\infty}f(n+2) \cdot Z^{-n} \cdot Z^{-2}}{Z^{-2}} - Z \cdot f(1) - Z^2 \cdot f(0) = Z^2F(Z) - Z^2f(0) - Zf(1) \]

\[ \sum_{n=-\infty}^{+\infty}f(n+1) \cdot Z^{-n} = \dfrac{\sum_{n=-1}^{+\infty}f(n+1) \cdot Z^{-n} \cdot Z^{-1}}{Z^{-1}} - Z \cdot f(0) = ZF(Z) - Zf(0) \]

\[ \sum_{n=-\infty}^{+\infty}f(n) \cdot Z^{-n} = F(Z) \]

所以有: \[ Z^{2}F(Z)-Z^{2}f(0) -Zf(1) = ZF(Z) - Zf(0) + F(Z) \] 又 \(f(0) = 0,f(1) = 1\),整理可得: \[ F(Z) = \dfrac{Z}{Z^{2} - Z} = \dfrac{1}{\sqrt{5}}\left(\dfrac{Z}{Z-\dfrac{1 + \sqrt{5}}{2}} - \dfrac{Z}{Z-\dfrac{1 - \sqrt{5}}{2}}\right) \] 我们取 \(Z\) 的逆变换可得: \[ f(n) = \dfrac{(\dfrac{1+\sqrt{5}}{2})^n - (\dfrac{1-\sqrt{5}}{2})^n}{\sqrt{5}}, (n > 1) \] 我们最终可以得到如下通项公式: \[ a_n = \dfrac{(\dfrac{1+\sqrt{5}}{2})^n - (\dfrac{1-\sqrt{5}}{2})^n}{\sqrt{5}}, (n> = 0) \] 更多的证明方法可以参考知乎上的一些数学大佬:https://www.zhihu.com/question/25217301

实现过程如下:

时间复杂度:\(O(1)\) 空间复杂度:\(O(1)\)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
纯公式求解
*/
int Fibonacci_formula(int num){
    double root_five = sqrt(5 * 1.0);
    int result = ((((1 + root_five) / 2, num)) - (((1 - root_five) / 2, num))) / root_five
    return result;
}

该方法虽然看起来高效,但是由于涉及大量浮点运算,在 \(n\) 增大时浮点误差不断增大会导致返回结果不正确甚至数据溢出。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-07-16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
浅谈什么是递归算法
程序调用自身的编程技巧称为递归( recursion)。递归作为一种算法在程序设计语言中广泛应用。一个方法或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。   例如求和问题:若要求解S100 = 1 + 2 + 3 + 4 + …. + 100的值,通过循环的方式代码如下:
五分钟学算法
2019/05/10
1K0
【数据结构与算法】时间复杂度和空间复杂度
数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。
平凡的人1
2022/11/15
3100
【数据结构与算法】时间复杂度和空间复杂度
【算法与数据结构】复杂度深度解析(超详解)
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
学习起来吧
2024/02/29
2750
【算法与数据结构】复杂度深度解析(超详解)
各种递归算法
斐波那契数列 定义: 斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368........,这个数列从第3项开始,每一项都等于前两项之和。 斐波那契数列又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。在数学上,斐波纳契数列以如下被以递归的
说故事的五公子
2019/09/11
5330
各种递归算法
Python 算法基础篇:时间复杂度和空间复杂度简介
在学习和分析算法时,时间复杂度和空间复杂度是两个关键概念。它们帮助我们评估算法的性能和资源使用情况。本篇博客将为你介绍时间复杂度和空间复杂度的概念,并通过 Python 示例代码演示它们的应用。
小蓝枣
2023/07/24
1.1K0
Python 算法基础篇:时间复杂度和空间复杂度简介
【基础算法】递归算法
递归算法是一种直接或间接调用原算法的算法,一个使用函数自身给出定义的函数被称为递归函数。利用递归算法可以将规模庞大的问题拆分成规模较小的问题,从而使问题简化。无论是递归算法还是递归函数,最大的特点都是“自己调用自己”。
WuShF
2023/07/08
4680
【基础算法】递归算法
【初阶数据结构】算法复杂度
对于我们所要解决的问题来说,解决的方法各有不同,每个人各有各的道理,并且受制于所用的设备的性能环境不同,我们很难精确比较一些方法不太明显的差别,因此,如何脱离环境直接衡量一个算法本身的好坏呢?比如对于以下斐波那契数列:
ZLRRLZ
2024/12/13
1360
【初阶数据结构】算法复杂度
【蓝桥杯Java_C组·从零开始卷】第七节、递归
你打开面前这扇门,看到屋里面还有一扇门。你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开它。若干次之后,你打开面前的门后,发现只有一间屋子,没有门了。然后,你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你可以回答出你到底用这你把钥匙打开了几扇门。
红目香薰
2022/11/29
3740
【蓝桥杯Java_C组·从零开始卷】第七节、递归
复杂度讲解
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源 。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。
waves浪游
2024/05/24
850
复杂度讲解
【数据结构】时间复杂度与空间复杂度
数据结构是什么呢?其实数据结构就是计算机存储和组织数据的一种形式,这些数据存在一种或多种特定关系的数据元素的集合。 算法又是什么?数值分析中我们对一个复杂的数学问题,会通过设定特定的算法将这个复杂的数学问题转化成加减乘除进行计算,这也是算法,事实上,算法就是定义良好的计算过程,用来将输入的数据转化成输出结果。
HABuo
2024/11/19
730
【数据结构】时间复杂度与空间复杂度
【数据结构与算法】【小白也能学的数据结构与算法】递归 分治 迭代 动态规划 无从下手?一文通!!!
递归是一种强大的问题解决方法,通过将问题分解为子问题并通过调用自身来解决。在本篇博客中,我们将深入了解递归的概念和基本原理,并使用C语言实现一些示例代码。
苏泽
2024/03/01
1830
【时间复杂度空间复杂度】
当文件没有进行保存时,这个文件保留在内存中,一旦断电,文件将无法保存,因此为了避免这种情况的发生,,处理文件之后,应该及时的ctrl+s保存到磁盘当中去。
每天都要进步呀
2023/03/28
1.7K0
【时间复杂度空间复杂度】
算法题目(二)
题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为旋转。 输入一个递增的排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小元素为1.
Helloted
2022/06/06
3560
算法题目(二)
数据结构 | 时间复杂度与空间复杂度
复杂度是衡量一个算法好坏的标准,可以从 时间 和 空间 两个维度进行比较。可能你之前听说某个算法的时间复杂度是O(N),空间复杂度是O(1),知道这是一个还不错的算法,那么你知道这些复杂度是如何计算出来的吗?本文将会揭开它们神秘的面纱,让你拥有一把衡量算法好坏的度量衡。
北 海
2023/07/01
2800
数据结构 | 时间复杂度与空间复杂度
算法的时间复杂度(详解)
算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为 输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果
用户11375356
2024/11/22
5570
算法的时间复杂度(详解)
算法复杂度分析
为什么要进行算法分析? 预测算法所需的资源 计算时间(CPU 消耗) 内存空间(RAM 消耗) 通信时间(带宽消耗) 预测算法的运行时间 在给定输入规模时,所执行的基本操作数量。 或者称为算法复杂度(Algorithm Complexity) 如何衡量算法复杂度? 内存(Memory) 时间(Time) 指令的数量(Number of Steps) 特定操作的数量 磁盘访问数量 网络包数量 渐进复杂度(Asymptotic Complexity) 算法的运行时间与什么相关? 取决于输入的数据。(例如:如果
前朝楚水
2018/04/02
1.1K0
算法复杂度分析
【数据结构与算法】时间复杂度与空间复杂度
早期,计算机刚被发明出来,内存空间并不是很大,所以不仅追求程序运行时的时间效率,还追求空间效率,但发展到今天,已经不太追求空间效率了,时间效率的追求是不变的。
aosei
2024/01/23
1290
【数据结构与算法】时间复杂度与空间复杂度
【初阶数据结构】时空罗盘妙解:时间复杂度&&空间复杂度
本篇开启数据结构初阶的学习,数据结构的重要性已经不言而喻,无论是在面试还是工作的时候,都占据重要的地位,面对海量数据或复杂逻辑关系,巧妙运用数据结构可梳理问题脉络,找到简洁的解题思路📖
DARLING Zero two
2025/01/20
1420
【初阶数据结构】时空罗盘妙解:时间复杂度&&空间复杂度
数据结构初步(一)- 时间与空间复杂度
当当当,本节开始进入到数据结构的学习之旅。什么是数据结构呢,什么又是时间复杂度与空间复杂度呢?学习数据结构的道路并不是一帆风顺的,唯有持续冲锋数据结构的高地。
怠惰的未禾
2023/04/27
6000
数据结构初步(一)- 时间与空间复杂度
【初阶数据结构】时间复杂度和空间复杂度(超有趣+超详细)
作为一位程序员,一颗强有力的好胜心和对知识充满渴望的眼神是必不可少的。如果你还拥有一头秀发,那更是程序员界中的佼佼者(开玩笑)😊。
埋头编程
2024/10/16
1630
推荐阅读
相关推荐
浅谈什么是递归算法
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验