数据结构与算法: 递归范式

概述

在算法中,递归是一种解决问题的常见方法,即通过在函数内调用自身来解决问题。
以下是常见的几种递归模式:

基本递归(Binary Recursion)

这是最基本的递归模式,它将计算分为两个部分,然后对每个部分单独进行递归处理。

int binaryRecursion(int n) {
    if (n == 0 || n == 1)
        return 1;
    else
        return binaryRecursion(n - 1) + binaryRecursion(n - 2);
}

尾递归(Tail Recursion)

指递归第一件事就是做一个递归调用。
我们可以把这种情况优化成迭代,因为调用不会回来了。

void tailRecursion(int n) {
    if (n == 0) return;    
    cout << n << endl;    
    tailRecursion(n - 1); // Tail call
}

维基百科尾递归:
若函数在尾位置调用自身(或是一个尾调用本身的其他函数等等),则称这种情况为尾递归。尾递归也是递归的一种特殊情形。尾递归是一种特殊的尾调用,即在尾部直接调用自身的递归函数。对尾递归的优化也是关注尾调用的主要原因。尾调用不一定是递归调用,但是尾递归特别有用,也比较容易实现。

特点:
尾递归在普通尾调用的基础上,多出了2个特征:

  1. 在尾部调用的是函数自身 (Self-called);
  2. 可通过优化,使得计算仅占用常量栈空间 (Stack Space)

头递归

头递归函数在调用自身之后,存在后续操作,而尾递归则在函数的最后一步调用自身。

// Head Recurison
int factorial(int n)
{
    if (n==1)
    {
    return 1;
    }
    return factorial(n-1)*n;
}

回溯(Backtracking)

常常用于寻找所有解决方案的问题,在每次递归时创建并向搜索树添加新的节点
当遇到满足条件的结果时,将结果存储下来;
如果不符合条件,则返回上一个节点并从集成的节点中删除它。

void backtracking(string comb, string digits, vector<string>& res, const vector<string>& v) {
    if (digits.empty()) { // 找到一个正确的匹配组合
        res.push_back(comb);
        return;
    }

    char digit = digits[0];
    string letters = v[digit - '0'];
    for (int i = 0; i < letters.size(); ++i) {
        backtracking(comb + letters[i], digits.substr(1), res, v);
    }
}

分治(Divide and Conquer)

将问题分成许多子问题,并将每个子问题的求解结果合并起来得到整个问题的解决办法。

vector<int> divideConquer(vector<int>& nums, int left, int right) {
    if (left == right) // 如果只有一个元素则直接返回
        return {nums[left]};

    vector<int> res;
    // 分割数组,对左右两部分分别使用divideConquer方法
    int mid = left + (right - left) / 2;
    vector<int> leftVals = divideConquer(nums, left, mid);
    vector<int> rightVals = divideConquer(nums, mid + 1, right);

    // 合并左右两部分的结果
    int i = 0, j = 0;
    while (i < leftVals.size() && j < rightVals.size()) {
        if (leftVals[i] < rightVals[j]) {
            res.push_back(leftVals[i++]);
        } else {
            res.push_back(rightVals[j++]);
        }
    }
    while (i < leftVals.size()) {
        res.push_back(leftVals[i++]);
    }
    while (j < rightVals.size()) {
        res.push_back(rightVals[j++]);
    }

    return res;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FLOWVERSE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值