文章目录
一、递归与分治概述:
1.分治法的设计思想
- 将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之
分治法的可行性(前提条件):
- ①如果原问题可以分成k个子问题,1<k<=n
- ② 子问题都可解
- ③ 可利用子问题的解求出原问题的解
- 问题分解是求解复杂问题时很自然的做法。
- 求解一个复杂问题可以将其分解成若干个子问题,子问题还可以进一步分解成更小的问题,直到分解所得的小问题是一些基本问题,并且其求解方法是已知的,可以直接求解为止。
- 将要求解的较大规模的问题分割成k个更小规模的子问题。
- 对这k个子问题分别求解。如果子问题的规模仍然不够小,则再划分为k个子问题,如此递归的进行下去,直到问题规模足够小,很容易求出其解为止。
- 将求出的小规模的问题的解合并为一个更大规模的问题的解,自底向上逐步求出原来问题的解。
通常,由分治法所得到的子问题与原问题具有相同的类型。如果得到的子问题相对来说还太大,则可反复使用分治策略将这些子问题分成更小的同类型子问题,直至产生出不用进一步细分就可求解的子问题。由此可知,分治法求解很自然地可用一个递归过程来表示。
总而言之:分治法作为一种算法设计策略,要求分解所得的子问题是同类问题,并要求原问题的解可以通过组合子问题的解来获取
2、递归的概念
定义:
直接或间接地调用自身的算法称为递归算法。
用函数自身给出定义的函数称为递归函数。
由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便:
在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子
问题缩小到很容易直接求出其解。
这自然导致递归过程的产生。
分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
- 递归的使用场合
① 数据结构本身是递归定义的,其实现算法往往是递归算法,比如二叉树和图等
② 求解过程需要递归,算法描述简捷其易于理解及分析,比如阶乘计算
使用例子
//1.阶乘
int factorial(int n)
{
if (n==0)
return 1;
return n*factorial(n-1);
}
//2.第n个Fibonacci数可递归地计算如下
int fibonacci(int n)
{
if (n <= 1)
return 1;
return fibonacci(n-1)+fibonacci(n-2);
}
//3.Ackerman函数
public class Ackerman {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m = scan.nextInt();
System.out.println(Ackerman1(n, m));
}
public static int Ackerman1(int n,int m){
if(n==0 && m>=0)return 1;
if(n==1 && m==0)return 2;
if(n>=2 && m==0)return n+2;
if(n>=1 && m>=1)
return Ackerman1(Ackerman1(n-1,m),m-1);
return -1;
}
}
//4 排列问题