遞歸算法的簡單理解

遞歸算法

程序調用自身的編程技巧稱爲遞歸( recursion)。遞歸做爲一種算法在程序設計語言中廣泛應用。 一個過程或函數在其定義或說明中有直接或間接調用自身的一種方法,它通常把一個大型複雜的問題層層轉化爲一個與原問題相似的規模較小的問題來求解,遞歸策略只需少量的程序就可描述出解題過程所需要的多次重複計算,大大地減少了程序的代碼量。遞歸的能力在於用有限的語句來定義對象的無限集合。一般來說,遞歸需要有邊界條件、遞歸前進段和遞歸返回段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。

遞歸算法兩大要素

1.確定遞歸公式
2.確定邊界(終了)條件

幫助理解小案例(java實現)

求數組中的最大數

RecursionMaxArrayTest.java

/**
 * java遞歸方法求數組最大元素
 * 思路:拿比較後的前兩個元素去和第三個元素比較......以此類推求出最大值
 * @author Scen
 * @date 2018/11/5 11:04
 */
public class RecursionMaxArrayTest {
    public static void main(String[] args) {
        int[] array = {6, 1, 5, 4, 8, 3, 9, 12, 51, 11, 15, 14, 13, 25, 69, 47, 56, 74, 26, 78};
        System.out.print(maxNum(array,array.length-1));
    }
    
    private static int max(int a, int b) {
        return a > b ? a : b;
    }
    
    private static int maxNum(int[] arr, int endIndex) {
//        邊界
        if (endIndex == 0) {
            return arr[0];
        }
//        遞歸公式
        return max(arr[endIndex], maxNum(arr, endIndex - 1));
    }
    
    
}

對1+2+3+…+n進行求和

Recursion12nTest.java

/**
 * java遞歸實現1+2+3+...+n
 * 思路:拿第一個元素和第二個元素的和去加第三個元素...以此類推
 * @author Scen
 * @date 2018/11/5 11:29
 */
public class Recursion12nTest {
    public static void main(String[] args) {
        System.out.println(sum12n(100));
    }
    
    private static int sum(int a, int b) {
        return a + b;
    }
    
    private static int sum12n(int n) {
//        邊界
        if (n == 0) {
            return 0;
        }
//        遞歸公式
        return sum(n, sum12n(n-1));
    }
}

求n個整數的積

RecursionProductTest.java

/**
 * java遞歸實現求n個整數的積
 * 思路:拿第一個元素和第二個元素的乘積去乘以第三個元素...以此類推
 * @author Scen
 * @date 2018/11/5 11:46
 */
public class RecursionProductTest {
    
    public static void main(String[] args) {
        int[] n = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        System.out.println(productN(n, n.length - 1));
    }
    
    private static int product(int a, int b) {
        return a * b;
    }
    
    private static int productN(int[] arr, int endIndex) {
        if (endIndex < 0) {
            return 1;
        }
        return product(arr[endIndex], productN(arr, endIndex - 1));
    }
}

求n個整數的平均值

RecursionAveragetTest.java

/**
 * java遞歸求n個整數的平均值
 * 思路:求和後除以個數
 * @author Scen
 * @date 2018/11/5 12:00
 */
public class RecursionAveragetTest {
    
    
    public static void main(String[] args) {
        int[] array = {1,2,3,4,9};
        System.out.println(averageN(array, 0, 0));
    }
    
    
    private static float averageN(int[] a, float sum, int index) {
//        邊界
        if (index ==a.length) {
            return sum/index;
        }
//        遞歸公式
        return averageN(a, sum += a[index], index + 1);
    }
    
}

求n個自然數的最大公約數與最小公倍數

RecursionGcdAndLcmTest.java

/**
 * java求n個自然數的最大公約數與最小公倍數
 * 思路:拿第一個元素和第二個元素的最大公約數(最小公倍數)去和第三個元素進行求取運算
 * ...以此類推
 * @author Scen
 * @date 2018/11/5 15:53
 */
public class RecursionGcdAndLcmTest {
    
    
    public static void main(String[] args) {
        int[] arr = {3,5,7};
        System.out.println(gcdN(arr,arr.length));
        System.out.println(lcmN(arr,arr.length));
    }
    
    private static int gcd(int m, int n) {
        if (m < n) {
            int temp = m;
            m = n;
            n = temp;
        }
//        邊界
        if (n == 0) {
            return m;
        }
//        遞歸公式
        return gcd(n, m % n);
    }
    
    private static int lcm(int m, int n) {
        return m * n / gcd(m, n);
    }
    
    private static int gcdN(int[] a, int endIndex) {
//        邊界
        if (endIndex == 0) {
            return a[0];
        }
//        遞歸公式
        return gcd(a[endIndex-1], gcdN(a, endIndex-1));
    }
    
    private static int lcmN(int[] a, int endIndex) {
//        邊界
        if (endIndex == 0) {
            return a[0];
        }
//        遞歸公式
        return lcm(a[endIndex - 1], lcmN(a, endIndex - 1));
    }
    
    
    
}

有一對雌雄兔,每兩個月就繁殖雌雄各一對兔子.問n個月後共有多少對兔子(斐波拉契數列)

RecursionFibonacciTest.java

/**
 * 有一對雌雄兔,每兩個月就繁殖雌雄各一對兔子.問n個月後共有多少對兔子(斐波拉契數列)
 * 思路:把問題抽象成一個函數f(n)=f(n-1)+f(n-2)(n>=3)
 * @author Scen
 * @date 2018/11/5 17:25
 */
public class RecursionFibonacciTest {
    
    public static void main(String[] args) {
        System.out.println(fibonacci(12));
    }
    
    public static int fibonacci(int n) {
//       邊界
        if (n < 3) {
            return 1;
        }
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

已知:數列1,1,2,4,7,13,24,44,…求數列的第 n項.

RecursionSequenceTest.java

/**
 * java已知:數列1,1,2,4,7,13,24,44,...求數列的第 n項.
 * 思路:把問題抽象成一個函數f(n)=f(n-1)+f(n-2)+f(n-3)(n>=4)
 * @author Scen
 * @date 2018/11/5 18:48
 */
public class RecursionSequenceTest {
    
    public static void main(String[] args) {
        System.out.println(sequence(8));
    }
    
    private static int sequence(int n) {
        if (n < 4) {
            switch (n) {
                case 3:
                    return 2;
                default:
                    return 1;
            }
        }
        return sequence(n - 1) + sequence(n - 2) + sequence(n - 3);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章