内功修炼——递归 分治

参考文章

一、D&C:分而治之,它是一种著名的递归式问题解决方法。

步骤:
(1)找出基线条件,这种条件必须尽可能简单。相当与递归的终止条件。
	  在处理列表时,基线条件很可能是空数组或只包含一个元素
(2)不断将问题分解(或者说缩小规模),直到符合基线条件

1. 自顶向下叫做递归,自底向上叫做递推

// 问题:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法?

// 1. 递归
   public int f(int n) {
       if (n <= 2) {
           return n;
       } else {
           return f(n - 1) + f(n - 2);
       }
   }
   
// 2. 备忘录法
//数组的大小根据具体情况来,由于int数组元素的的默认值是0
//因此我们不用初始化
   int[] arr = new int[1000];
   public int f(int n) {
       if (n <= 2) {
           return n;
       } else {
           if (arr[n] != 0) {
               return arr[n];//已经计算过,直接返回
           } else {
               arr[n] = f(n-1) + f(n-2);
               return arr[n];
           }
       }
   }

// 3. 自底向上
public int f(int n) {
       if(n <= 2)
           return n;

       int f1 = 1;
       int f2 = 2;
       int sum = 0;

       for (int i = 3; i <= n; i++) {
           sum = f1 + f2;
           f1 = f2;
           f2 = sum;
       }
       return sum;
   }

2. 当你在使用递归解决问题的时候,要考虑以下两个问题

  1. 是否有状态重复计算的,可不可以使用备忘录法来优化。
  2. 是否可以采取递推的方法来自底向上做,减少一味递归的开销。

3. 遇到递归的题,一定要考虑是否可以剪枝,是否可以把递归转化成递推。

二、常见的分治题型

大多数应该运用于一维题目中,例如字符串、一维数组相关的题,可以考虑使用分治的方法

例题1:二路归并排序

# 二路归并排序 递归
# 两两合并,分治    
def merge(arr, left, mid, right):
    i = left
    j = mid
    res = []
    while i < mid and j < right+1:
        if arr[i] > arr[j]:
            res.append(arr[j])
            j = j + 1
        else:
            res.append(arr[i])
            i = i + 1
    
    while i < mid:
        res.append(arr[i])
        i = i + 1
    while j < right + 1:
        res.append(arr[j])
        j = j + 1
    p = len(res)
    for k in range(p):
        arr[left+k] = res[k]


def mergeSort(arr, left, right):
    # 基准因子, 当只剩一个元素时, 直接返回
    if left >= right:
        return
    
    mid = right + int((left - right)/2)

    # 左边数组进行归并排序
    mergeSort(arr, left, mid-1)

    # 右边数组进行归并排序
    mergeSort(arr, mid, right)

    # 判断升序时返回
    if arr[mid-1] <= arr[mid]:
        return
    
    merge(arr, left, mid, right)

写在最后

如果觉得本文对你有帮助的话,可以为我点个赞哈,你的关注和支持是我坚持下去最大的鼓励。

对文章有什么建议和意见,也欢迎留言告诉我,期待你的回馈。

发布了13 篇原创文章 · 获赞 13 · 访问量 636

猜你喜欢

转载自blog.csdn.net/coding_sleep/article/details/105290665