美文网首页
思想 / 递归和分治

思想 / 递归和分治

作者: 原创迷恋者 | 来源:发表于2019-08-19 14:48 被阅读0次

    递归
    递归在程序语言中简单的理解是:方法自己调用自己。递归和循环是非常像的,循环都可以改写成递归,递归未必能改写成循环,这是一个充分不必要的条件。

    我们要记住的是,想要用递归必须知道两个条件:

    1. 递归出口(终止递归的条件)
    2. 递归表达式(规律)

    技巧:在递归中常常是将问题切割成两个部分(1和整体的思想),这能够让我们快速找到递归表达式(规律)

    分治
    在计算机科学中,分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)。

    任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的

    分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

    分治法适用的情况
    分治法所能解决的问题一般具有以下几个特征:
    1) 该问题的规模缩小到一定的程度就可以容易地解决
    2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
    3) 利用该问题分解出的子问题的解可以合并为该问题的解;
    4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。

    第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;
    第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;
    第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。
    第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。

    分治法的基本步骤
    分治法在每一层递归上都有三个步骤:
    step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
    step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
    step3 合并:将各个子问题的解合并为原问题的解。

    递归的例子
    一、求和
    如果我们使用for循环来进行求和1+2+3+4+....+100,那是很简单的:

    int sum = 0;
    for (int i = 1; i <= 100; i++) {
      sum = sum + i;
    }
    

    首先,我们来找出它的规律:1+2+3+...+n,这是一个求和的运算,那么我们可以假设X=1+2+3+...+n,可以将1+2+3+...+(n-1)看成是一个整体。而这个整体做的事又和我们的初始目的(求和)相同。以我们的高中数学知识我们又可以将上面的式子看成X=sum(n-1)+n。

    public static int sum(int n) {
      if (n == 1) {
          return 1;
      } 
      else {
          return sum(n - 1) + n;
      }
    

    相关文章

      网友评论

          本文标题:思想 / 递归和分治

          本文链接:https://www.haomeiwen.com/subject/sqwjsctx.html