藍橋杯——巧妙地遞迴

Meteor發表於2023-01-04

一、切蛋糕思想

  • 對於遞迴,我們可以採用思想之一,切蛋糕思想。
  • 簡而言之,就是將一個大問題,切成若干個小問題進行解決。
  • 遞迴三要素:找重複、找變化、找邊界
  • 我們可以理解為,自己處理一小部分,剩下的部分交給別人處理(遞迴)
  • 分解為:直接量 + 小規模子問題

1.1 經典求階乘

  • 求階乘
    • jc(n):求n的階乘 jc(n-1):求n-1的階乘
    • 1.找重複: n*(n-1) ————子問題
    • 2.找變化:變化的量應該作為引數
    • 3.找邊界:出口
public class 遞迴 {
    public static int jc(int n) {
        if(n == 1)
            return 1;
        return n * jc(n-1);
    }
}

1.2 列印i到j

  • 1.找重複:理解為我處理當前引數問題,剩下的部分交給這個函式處理(規模更小的子問題)
  • 2.找變化:變化的量應該作為引數
  • 3.找邊界:出口
public static void print(int i, int j) {
        // 出口
        if(i > j) return;
        System.out.println(i);
        // 重複與變化
        print(i+1,j);
    }

1.3 陣列求和

  • 當我們發現無法進行遞迴時,肯定是我們的引數不夠
 public static int sum(int[] arr,int start) {
        if(start == arr.length)
            return 0;
        return arr[start] + sum(arr,start+1);
    }

1.4 翻轉字串

  • 使用遞迴對一個字串進行翻轉
public static String reverse(String str, int end) {
        if(end == 0)
            return ""+str.charAt(0);
        return str.charAt(end) + reverse(str,end-1);
    }

二、遞迴公式與等價轉換思想

  • 和上面切蛋糕思想不同的是,這種問題我們無法進行切分,但是我們都可以轉換成數學問題,當找到數學問題後進行等價轉換即可。
  • 分解為:多個子規模小問題

2.1 經典斐波那契數列

  • F(n) = F(n-1) + F(n-2)
// 求斐波那契數列第n項的值
public static int fib(int n) {
        // 3. 找出口
        if(n == 1 || n == 2) return 1;
        // 1.找變化 | 2.找重複
        return fib(n-1) + fib(n-2);
    }

2.2 最大公約數

  • 經典的歐幾里得演算法也稱之為輾轉相除法
  • 透過最大公約數我們也可以判斷兩個數是否互質
  • F(m,n) = F(n,m%n)
public static int zzxc(int m, int n) {
        if(n == 0) return m;
        return zzxc(n,m%n);
    }

2.3 遞迴形式的插入排序

  • 同樣是利用切分思想,我們對陣列前k-1個元素進行排序
  • 最後處理最後一個單獨的元素
  • 遞迴都是父問題轉換成子問題
public static void insertArr(int[] arr, int k) {
        // 1.對陣列前k-1個元素進行排序
        insertArr(arr, k - 1);

        // 2.將最後一個元素插入到排好序的陣列中
        int temp = arr[k]; // 記錄該數
        while(temp < arr[k-1]) { // 後一個數比前一個數小的情況,將大的數後移
            arr[k] = arr[k-1];  // 直到找到適合自己的位置為止
            k--;
        }
        arr[k] = temp;
    }

三、搞不清楚的漢諾塔

  • 1~N從A移動到B,C作為輔助

等價於:

  1. 1~N-1從A移動到C,B為輔助

  2. 把N從A移動到B

  3. 1~N-1從C移動到B,A為輔助

	/**
     * 八、漢諾塔問題
     * 將N個盤子從source移動到target的路徑列印
     * @param N 初始的N個從小到大的盤子,N是最大編號
     * @param from 原始柱子
     * @param help 輔助的柱子
     * @param to 目標柱子
     */
    public static void printHanoiTower(int N, String from, String to, String help) {

        printHanoiTower(N-1, from, help, to);
        System.out.println("move" + N + "from" + from + "to" + to);
        printHanoiTower(N-1, help, to, from);
    }

四、結尾

  • 對於藍橋杯遞迴知識內容就總結這麼多,若想深入學習等待後續更新。
  • 我將會繼續更新關於藍橋杯方向的學習知識,感興趣的小夥伴可以關注一下。
  • 文章寫得比較走心,用了很長時間,絕對不是copy過來的!
  • 尊重每一位學習知識的人,同時也尊重每一位分享知識的人。
  • ?你的點贊與關注,是我努力前行的無限動力。?