假如我们把函数都改成递归...

这篇具有很好参考价值的文章主要介绍了假如我们把函数都改成递归...。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  学算法阶段时不时会遇到一些递归的应用场景,例如DFS,二叉树等相关的题目,递归常常能大展身手。不过有意思的一件事情是,若我们把一些本该迭代的算法改成递归实现,会是什么样的情形。

  这是一个很简单的矩阵加法的例子。

void matrixAdd(const std::vector<std::vector<int>>& a,
               const std::vector<std::vector<int>>& b,
               std::vector<std::vector<int>>& c)
{
    int n1 = a.size(), m1 = a[0].size();
    int n2 = b.size(), m2 = b[0].size();
    assert(n1 == n2 && m1 == m2);

    for (int i = 0; i < n1; ++i)
    {
        for (int j = 0; j < m1; ++j)
        {
            c[i][j] = a[i][j] + b[i][j];
        }
    }
}

  同样有递归版本,很多时候这两者都是可以相互转换的。

void __matrixAdd(const std::vector<std::vector<int>>& a, const std::vector<std::vector<int>>& b,
                 std::vector<std::vector<int>>& c, int row, int col)
{
    if (row == static_cast<int>(a.size()))
        return;
    if (col == static_cast<int>(a[0].size()))
    {
        __matrixAdd(a, b, c, row + 1, 0);
        return;
    }

    c[row][col] = a[row][col] + b[row][col];
    __matrixAdd(a, b, c, row, col + 1);
}

void matrixAdd(const std::vector<std::vector<int>>& a,
               const std::vector<std::vector<int>>& b,
               std::vector<std::vector<int>>& c)
{
    int n1 = a.size(), m1 = a[0].size();
    int n2 = b.size(), m2 = b[0].size();
    assert(n1 == n2 && m1 == m2);
    __matrixAdd(a, b, c, 0, 0);
}

  当row越界的时候,直接return不用再往下操作了;而当col越界的时候,可以往下一行重新进行相加操作,这里也要return,不然后续的操作会导致越界。可以直观看到代码并没有用到for循环,看起来比较简练。接下来是冒泡排序。

void bubbleSort(std::vector<int>& arr) {
    int n = arr.size();

    // 进行 n-1 轮的冒泡排序
    for (int i = 0; i < n - 1; i++) {
        // 在每一轮中,比较相邻的两个元素,将较大的元素向后移动
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                std::swap(arr[j], arr[j + 1]);
            }
        }
    }
}
void bubbleSortRecursive(std::vector<int>& arr, int n) {
    // 基本情况:如果只剩下一个元素,已经有序
    if (n == 1) {
        return;
    }

    // 一次遍历,将最大的元素移动到末尾
    for (int i = 0; i < n - 1; i++) {
        if (arr[i] > arr[i + 1]) {
            std::swap(arr[i], arr[i + 1]);
        }
    }

    // 递归调用,对除了最后一个元素的子数组进行排序
    bubbleSortRecursive(arr, n - 1);
}

  相比原来的迭代版本少了一个for循环,代码量相差不大。再来看看斐波那契数列,通常它的递归实现是只保留最后一项的,我们也可以写一个保留中间计算过程的版本。

int fib(std::vector<int>& arr, int n) {
    if (n <= 1) {
        arr[n] = n;
        return arr[n];
    }

    arr[n] = fib(arr, n - 1) + fib(arr, n - 2);
    return arr[n];
}

  字符串翻转也是很容易实现的。

void reverseString(std::string& str, int left, int right) {
    if (left >= right) {
        return;
    }

    // 交换左右字符
    std::swap(str[left], str[right]);

    // 递归翻转剩余部分
    reverseString(str, left + 1, right - 1);
}

  先到这里,有什么好的想法也可以提一提~文章来源地址https://www.toymoban.com/news/detail-760175.html

到了这里,关于假如我们把函数都改成递归...的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 掌握Go语言:探索Go语言递归函数的高级奥秘,优化性能、实现并发、解决算法难题(28)

    递归函数在Go语言中是一种强大的工具,能够解决许多复杂的问题。除了基本的递归用法外,Go语言还提供了一些高级用法,使得递归函数更加灵活和强大。本文将深入探讨Go语言递归函数的高级用法,包括尾递归优化、并发递归和记忆化递归等。 尾递归优化 尾递归是一种特

    2024年04月10日
    浏览(41)
  • c#调用cpp库,debug时不进入cpp函数

    选中c#的项目,右击属性,进入属性页,点击调试,点击打开 调试启动配置文件UI ,打开 启用本机代码调试 。

    2024年02月16日
    浏览(31)
  • 一种基于注意机制的快速、鲁棒的混合气体识别和浓度检测算法,配备了具有双损失函数的递归神经网络

    提出一个由注意力机制组成的电子鼻系统。首先采用端到端的编码器译码器,提供处理可变长度输入的灵活性。然后提供一种新的门控循环单元网络,方便从时间动态中提取特征,在此基础上注意力机制动态分配气体特征的权重向量。最后采用双损失函数,利用同一网络实现

    2024年02月09日
    浏览(36)
  • uniapp TypeError: Cannot set property 改成箭头函数

    改成箭头函数 ,因为作用域不一样。 完美解决。 箭头函数相信大家在日常开发中用到的地方非常之多,因为它很简洁,可读性强,但是它最大的好处,其实是解决了匿名函数的this指向问题,有利于封装回调函数。 总结: 箭头函数体内的this对象,就是定义该函数时所在的作

    2024年02月12日
    浏览(39)
  • 【C&C++】为什么 scanf 函数在读取字符串时不需要用取地址运算符 &

    在C语言中,字符串实际上是字符数组,所以我们可以使用 scanf 函数来读取字符串。但是,需要注意的是, scanf 在读取字符串时会在遇到空格、制表符或换行符时停止。因此,它不能用于读取包含空格的字符串。 以下是使用 scanf 读取字符串的基本示例: 在这个例子中,我们

    2024年01月20日
    浏览(39)
  • 【第一阶段】kotlin的函数

    函数头 执行结果 默认参数 有默认可不用传参数,也可以传值覆盖 执行结果 kotlin具名参数 在java中传参需要和调用方法的参数顺序保持一致,在kotlin中调用时可以直接根据参数名称来传入 执行结果 kotlin的Unit java语言的void(void是 无参数返回的 忽略类型)但他是

    2024年02月13日
    浏览(26)
  • 【第二阶段】kotlin函数引用

    针对上篇传入函数参数我们也可以重新定义一个函数,然后在main中调用时传入函数对象 lambda属于函数类型的对象,需要把普通函数变成函数类型的对象(函数引用),使用“::” 执行结果

    2024年02月12日
    浏览(28)
  • 将递归函数转成非递归函数的通用方法

    看到过一道非常不错的面试题:不支持递归的程序语言如何实现递归程序? 之所以说这道题好,是因为: 首先,它不是纯粹考概念和死记硬背,求职者在回答问题之前需要进行一定的思考; 其次,这道题目可以继续深挖,比如可以让求职者具体写一个程序,就变成了一道编

    2024年02月08日
    浏览(31)
  • 深度学习经典检测算法--单阶段、两阶段区别

     需要做一个检测任务 有的算法是分两个阶段的,有的算法是只有一个阶段  现在我们需要做一个猫咪的物体检测,输入一张图像有猫,输出的图像猫身上带了一个框 这个结果,框,我们只需要得到框的四个顶点坐标就可以实现 这就是一个很普通的回归任务 单阶段,一个

    2023年04月08日
    浏览(46)
  • 深入理解递归函数与可控递归的应用

    什么是递归函数 递归函数的本质与循环的关系 递归函数的特点与优势 可控递归的要素 使用C语言详细举例说明可控递归 注意事项:递归层数限制与堆栈溢出问题 递归函数是指函数自己调用自己的过程。在C语言中,通过递归调用,函数能够重复执行某个任务,直到满足特定

    2024年02月12日
    浏览(23)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包