分治与递归

分治与递归

1. 递归

两个核心

  • 子问题必须与原始问题相同,且规模更小(递归式)
  • 不能无限制地调用自身,必须有一个递归出口 (递归边界)

2.分治法

步骤

  • 分:将问题分解为规模更小的问题(严格来说根据这一步的不同还可能分为减治法和分治法)
  • 治:将这些规模更小的子问题逐个击破
  • 合:将已解决的子问题合并,最终得出“母”问题的解

跟递归的关系

分治法既可以用递归求解也可以不用递归求解,但是一般来说都是用递归求解的,因为用递归代码写起来更加容易,因此我们将上面两种算法合到一起举例

3.举例

例子

  • 汉诺塔1中移动次数计算(F(n) = 2 * F(n-1) + 1)
  • 汉诺塔2(每次只能移动至相邻的塔)中移动次数计算(F(n) = 3 * F(n-1) + 2)
  • 全排列问题
链接:https://www.nowcoder.com/questionTerminal/5632c23d0d654aecbc9315d1720421c1?f=discussion
来源:牛客网
//算法思想:全排列的n皇后问题思路,对问题进行递归实现。
//只不过将全排列的数字换为字母进行输出即可。
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn=7;//P为当前排列,hashTable记录x是否已经在p中
int n,hashTable[maxn]={false};//当前处理排列的index位
char p[maxn];//储存全排列结果的数组
void generateP(int index,char str[])
{
    if(index==n)//递归边界
    {
        for (int i = 0; i <n; ++i)
        {
            printf("%c", p[i]);//输出当前排列
        }
        printf("\n");
        return;
    }
    for (int x = 0; x <n; ++x)//枚举1~n,试图将x填入p【index】
    {
        if (hashTable[x]==false)//如果x不在p[0]~p[index-1]中
        {
            p[index]=str[x];//令p的index位为先,即把str[x]加入当前排列
            hashTable[x]=true;//记x已经在p中
            generateP(index+1,str);//处理排列的index+1位
            hashTable[x]=false;//已处理完p[index]为x的子问题,还原状态
        }
    }
}
int main(int argc, char const *argv[])
{
    char str[maxn];
    while(scanf("%s",str)!=EOF)
    {
        n=strlen(str);
        sort(str,str+n);//将原始数组进行大小排序
        generateP(0,str);
        printf("\n");
    }
    return 0;
}
  • n皇后问题(由上面的全排列问题改编而来,实际上还可以进一步通过回溯法进行剪枝,具体见算法笔记P117)
void generateP(int index)
{
    if (index == n + 1) //递归边界,生成一个排列
    {
        bool flag = true;            //flag为true表示当前排列为一个合法方案,
        for (int i = 1; i <= n; i++) //遍历任意两个皇后
        {
            for (int j = i + 1; j <= n; j++)
            {
                if (abs(i - j) == abs(P[i] - P[j])) //如果x方向和y方向的距离相等说明在一条对角线上
                {
                    flag = false;
                }
        }
        if (flag == true)
        {
					count++;
        }
        return;
    }
    for (int x = 1; x <= n; x++)
    {
        if (hashTable[x] == false)
        {
            P[index] = x;
            hashTable[x] = true;
            generateP(index + 1);
            hashTable[x] = false;
        }
    }
}

4.应用习题

二叉树(北京大学)

2的幂次方(上海交通大学)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值