首页 > 编程语言 >递归算法的时间复杂度(通过一道面试题来讲解)

递归算法的时间复杂度(通过一道面试题来讲解)

时间:2024-10-11 19:11:47浏览次数:1  
标签:面试题 return 递归 int 复杂度 面试官 算法

本篇通过一道简单的面试题,逐步分析递归算法的时间复杂度,最后找到最优解

同一道题目,同样使用递归算法,既可以写出时间复杂度为O(n)的代码,也可以写出时间复杂度为O(logn)的代码。

why?

这是因为对递归算法的时间复杂度理解不够深入。

下面通过一道面试题,来逐步分析递归算法的时间复杂度,最后找出最优解

面试题:求x的n次方

  • 最直观的方式应该就是,一个for循环求出结果,代码如下:

    int function1(int x, int n) {
        int result = 1;  // 注意 任何数的0次方等于1
        for (int i = 0; i < n; i++) {
            result = result * x;
        }
        return result;
    }
    

    时间复杂度为O(n),此时面试官会说,有没有效率更好的算法呢?

    面试者如果此时没有思路,建议不要说不知道。可以和面试官探讨一下,询问:“可不可以给点提示”。面试官提示说:“考虑一下递归算法”.

  • 此时面试者就写出了如下代码,使用递归算法解决了这个问题:

    int function2(int x, int n) {
        if (n == 0) {
            return 1; // return 1 同样是因为0次方是等于1的
        }
        return function2(x, n - 1) * x;
    }
    

    面试官问:“那么这个代码的时间复杂度是多少?”。

    一些同学可能一看到递归就想到了O(logn),其实并不是这样,递归算法的时间复杂度本质上是要看: 递归的次数 * 每次递归中的操作次数

    那么这里递归了几次呢?

    每次递归n都做一次减1的操作,那么就是递归了n次,递归n次时间复杂度是O(n),每次执行一个乘法操作,而乘法操作的时间复杂度是一个常数项O(1),所以这段代码的时间复杂度是O(n) (即:O(n*1) = O(n) )

    这个时间复杂度可能没有达到面试官的预期。

  • 于是面试者又些出了如下递归算法的代码:

    int function3(int x, int n) {
        if (n == 0) return 1;
        if (n == 1) return x;
    
        if (n % 2 == 1) {
            return function3(x, n / 2) * function3(x, n / 2)*x;
        }
        return function3(x, n / 2) * function3(x, n / 2);
    }
    

    面试官看到后微微一笑,问:“这段代码的时间复杂度又是多少呢?” 此时面试者陷入了沉思……

    首先看递归了多少次呢,可以把递归抽象出一棵满二叉树。刚刚同学写的这个算法,可以用一棵满二叉树来表示(为了方便表示,选择n为偶数16),如图:

    img

    当前这棵二叉树就是求x的n次方,n为16的情况,n为16的时候,进行了多少次乘法运算呢?

    这棵树上每一个节点就代表着一次递归并进行了一次相乘操作,所以进行了多少次递归的话,就是看这棵树上有多少个节点。

    熟悉二叉树话应该知道如何求满二叉树节点数量,这棵满二叉树的节点数量就是\(2^3 + 2^2 + 2^1 + 2^0 = 15\),可以发现:这其实是等比数列的求和公式,这个结论在二叉树相关的面试题里也经常出现。

    这么如果是求x的n次方,这个递归树有多少个节点呢,如下图所示:(m为深度,从0开始)

    img

    时间复杂度忽略掉常数项-1之后,这个递归算法的时间复杂度依然是O(n)。对,你没看错,依然是O(n)的时间复杂度!

    此时面试官就会说:“这个递归的算法依然还是O(n)啊”, 很明显没有达到面试官的预期。

  • 那么O(logn)的递归算法应该怎么写呢?

    想一想刚刚给出的那份递归算法的代码,是不是有哪里比较冗余呢,其实有重复计算的部分。

    于是又写出如下递归算法的代码:

    int function4(int x, int n) {
    if (n == 0) return 1;
    if (n == 1) return x;
    int t = function4(x, n / 2);// 这里相对于function3,是把这个递归操作抽取出来
    if (n % 2 == 1) {
        return t * t * x;
    }
    return t * t;
    }
    

    现在这段代码的时间复杂度是多少呢?

    这里仅有一个递归调用,而且每次递归操作的数据规模都除以2,所以这里一共调用了\(log_2 n\)次,每次递归操作都是一次乘法操作,这也是一个常数项的操作,所以这个递归算法的时间复杂度才是真正的O(logn)。

  • 恭喜你,通过了考验~~

标签:面试题,return,递归,int,复杂度,面试官,算法
From: https://www.cnblogs.com/hisun9/p/18459083

相关文章

  • 2024前端面试题!
    目录一、Html5、Css3篇1、HTML、XHTML、XML有什么区别?⭐2、XML和JSON的区别?3、是否了解W3C的规范?⭐4、什么是语义化标签?⭐⭐5、常用的块级元素和行内元素有哪一些?⭐6、行内元素和块级元素的区别?⭐7、css盒子模型有几种类型?它们区别是什么⭐8、标签上title与a......
  • 面试题速刷 - 知识广度
    网页和iframe如何通讯?(听都没听过iframe)---属于HTML中WebSocket内容iframe是HTML中的一个元素,它允许在一个HTML页面中嵌入另一个HTML页面。下面是对iframe的简要解释:定义:iframe代表"内联框架"(InlineFrame)。用途:它用于在当前网页中嵌入另一个独立的HTML文档。ifram......
  • html面试题总结
    文章目录1.什么是DOCTYPE,有何作用2.H5有哪些新的元素和新特性3.cookie、sessionStorage和localStorage的区别4.script、scriptasync和scriptdefer的区别5.行内元素有哪些?块级元素有哪些?空(void)元素有哪些?6.页面导入样式时,使用link和@import有什么区别7.title和h1......
  • 刷题计划 day12 二叉树(一)【定义】【递归遍历】【迭代遍历】
    ⚡刷题计划day12 二叉树(一)继续,这一小节主要是基础知识,但同样也是十分重要的,可以点个免费的赞哦~往期可看专栏,关注不迷路,您的支持是我的最大动力......
  • 2024前端高频面试题之一
    1.从输入URL到页面显示发生了什么(1)缓存查询(查询优先级:浏览器缓存,系统缓存,路由器缓存)(2)DNS解析,把网址解析唯一IP【网址是为了方便记忆】(3)执行tcp三次握手,建立http链接(4)浏览器拿到返回的数据渲染页面【可能存在跨域问题】(5)断开tcp连接2.fetch和ajax的......
  • 递归特征消除(RFE)与随机森林回归模型的 MATLAB 实现
    在机器学习中,特征选择是提高模型性能的重要步骤。本文将详细探讨使用递归特征消除(RFE)结合随机森林回归模型的实现,以研究对股票收盘价影响的特征。我们将逐步分析代码并介绍相关的数学原理。1.数据准备首先,我们清空工作区并加载数据,假设最后一列是股票的收盘价,前面的列是特征......
  • 300道金典Java面试题,常见面试题及答案汇总
    Q1:Java中变量可以既是局部变量又是静态变量吗?答案:不能,将局部变量定义为静态变量会导致编译错误。Q2:Interface中可以有静态方法吗?答案:Interface中的静态方法是没有意义的,静态方法在类中不能被覆盖,而Interface中的方法默认都是抽象的,所以只能在实现Interface的类中实现。Q3:在......
  • 链表【两数相加】具体思路——【递归】【迭代】【暴力】(附完整代码)
    文章目录前言一、问题引入,如何理解【链表】两数相加?二、方法一(固定数组暴力)三、方法二(递归法)四、方法三(迭代法)前言本文将介绍【链表】两数相加对于这一问题将采用多种思路方法来解决【暴力】【递归法】【迭代法】一、问题引入,如何理解【链表】两数相加?题目链接......
  • Ajax面试题:(第二天)
    目录5.http常见状态码有哪些?6.GET和POST的区别,何时使用POST?7.JSON是什么?JSON和JavaScript普通对象有什么区别?如何把JS对象转化为JSON字符串,又如何把JSON字符串转化为JavaScript对象?8.什么是ajax?ajax作用是什么?5.http常见状态码有哪些?小谷来帮你1XX:信息状态码2XX:成......
  • 快速排序的非递归实现:借助栈实现、借助队列实现
    目录用栈实现快速排序1.用栈实现非递归快速排序的思路步骤1.1.思路步骤2.用栈实现非递归快速排序的代码3.用栈实现非递归快速排序的整个工程3.1.QuickSortNonR.h3.2.QuickSortNonR.c3.3.Stack.h3.4.Stack.c用队列实现非递归快速排序1.用队列实现非递归快速排序的思......