1. 程式人生 > >左神第八課之遞迴演算法

左神第八課之遞迴演算法

題目一
求n!

簡單得不想說

題目二

漢諾塔問題
古代有一個梵塔,塔內有三個座A、B、C,A座上有64個盤子,盤子大小不等,大的在下,小的在上(如圖)。有一個和尚想把這64個盤子從A座移到C座,但每次只能允許移動一個盤子,並且在移動過程中,3個座上的盤子始終保持大盤在下,小盤在上。在移動過程中可以利用B座,要求輸出移動的步驟 。
這裡寫圖片描述

解答

把A上的盤子編號1,2,3,4(最大的),現在把4移到C只要1,2,3到B再把4移動到C,在把1,2,3移動到C


當搬運的碟子數n=1時,直接搬運即可;當n>1時,要把n個碟子從針1搬運到針3,則必須通過針2(即需要一個獨立於源針和目的針的中間針,用來輔助);假設我們已經成功的把上面較小的n-1個碟子搬運到了針2,那麼我們只需要再把第n個碟子(底層最大的那個)搬運到針3,再把針2的n-1個碟子搬運到針3,那麼這n個碟子塔就成功的搬運到了針3了.而整個n-1的塔要怎麼搬運呢?這就是遞迴啦
所以整個步驟:
1.搬運n-1個碟子到中間針(遞迴)
2.搬運第n個碟子到目的針
3.搬運中間針的n-1個碟子到目的針(遞迴)
void move (getone,putone)
函式的作用是用於搬運最底層的第n個碟子,從getone針搬到putone針
void hanoi (n,one,two,three)
函式的作用是,把n層塔從one針(源)搬運到three針(目的),用two針來輔助(中間)
所以上面的步驟就可以翻譯成c語言了
要想把n個碟子從one針搬運到three針的三個步驟:
(與第一段陳述的三個步驟對應,即hanoi(n,one,two,three)函式要完成的功能,函式主體)
1.hanoi(n-1,one,three,two);是遞迴呼叫,如果n-1>1則它又會去執行3個步驟,以至於無窮
2.move(one,three);這一步是具體移動,所以要輸出移動方法,讓使用者能看見移動方向
3.hanoi(n-1,two,one,three);遞迴
遞迴呼叫只要有整體觀念就行了,你在寫程式碼的過程中可以把”移動n-1個塔”看作一步完成的,至於這步是怎麼完成的,會由計算機逐級遞迴展開函式棧具體實現,我們不必多想.因為每一級的過程都是一樣的,所以用遞迴,減少程式碼規模
遞迴的思想相對較容易,即只看見本層次,低層次由於過程和本層完全相同,呼叫遞迴函式自身,來重複利用程式碼.由於會函式巢狀呼叫會有多餘的時間空間耗費,所以在遞迴次數過大等情況下,儘量用非遞迴的方法實現.

程式碼如下

public class Code_02_Hanoi {
    static int b=0;
    public static void hanoi(int n,String from, String help, String to) {
        if (n ==1) {
            System.out.printf("%d號盤:%s-->%s\n",n,from,to);
            b++;
        }else{
        hanoi(n-1,  from, to, help);
        System.out
.printf("%d號盤:%s-->%s\n",n ,from,to); hanoi(n-1, help, from, to); b++; } } public static void main(String[] args) { int n = 4; hanoi(n, "A", "B", "C"); System.out.println(b); } }

題目四

列印一個字串的全部排列

import java.util.LinkedList;
import java.util.List;

public
class Code_03_Print_All_Subsquences { public static List<List<Character>> ans = new LinkedList<List<Character>>(); public static LinkedList<Character> list = new LinkedList<Character>(); public static void printAllSubsquence(String str) { char[] chs = str.toCharArray(); process(chs, 0); } private static void process(char[] chs, int index) { if (index >= chs.length ) { LinkedList<Character> list2 = new LinkedList<Character>(); list2.addAll(list); ans.add(list2); return; } list.add(chs[index]); process(chs, index + 1); list.pollLast(); process(chs, index + 1); } public static void main(String[] args) { printAllSubsquence("123"); System.out.println(ans); } }

題目五

列印一個數字的全排列

package lesson8;

import java.util.LinkedList;
import java.util.List;

public class Code_04_Print_All_Permutations {

    public static List<List<Integer>> ans = new LinkedList<List<Integer>>();
    public static boolean[] v = new boolean[100];
    public static LinkedList<Integer> list = new LinkedList<Integer>();

    public static void robot(int index, int[] nums) {
        if (index >= nums.length) {
            List<Integer> list2 = new LinkedList<Integer>();
            list2.addAll(list);
            ans.add(list2);
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (v[i] == false) {
                v[i] = true;
                list.add(nums[i]);
                robot(index + 1, nums);
                list.pollLast();
                v[i] = false;
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = { 1, 2, 3 };
        robot(0, arr);
        System.out.println(ans);
    }

}

題目六

母牛每年生一隻母牛,新出生的母牛成長三年後也能每年生一隻母牛,假設不會死。求N年後,母牛的數量。

public class Code_05_Cow {

    public static int cowNumber1(int n) {
        if (n < 1) {
            return 0;
        }
        if (n == 1 || n == 2 || n == 3) {
            return n;
        }
        return cowNumber1(n - 1) + cowNumber1(n - 3);
    }

    public static int cowNumber2(int n) {
        if (n < 1) {
            return 0;
        }
        if (n == 1 || n == 2 || n == 3) {
            return n;
        }
        int res = 3;
        int pre = 2;
        int prepre = 1;
        int tmp1 = 0;
        int tmp2 = 0;
        for (int i = 4; i <= n; i++) {
            tmp1 = res;
            tmp2 = pre;
            res = res + prepre;
            pre = tmp1;
            prepre = tmp2;
        }
        return res;
    }

    public static void main(String[] args) {
        int n = 20;
        System.out.println(cowNumber1(n));
        System.out.println(cowNumber2(n));
    }

}

題目七

給你一個棧,請你逆序這個棧,不能申請額外的資料結構,只能使用遞迴函式。如何實現?

import java.util.Stack;

public class Code_06_ReverseStackUsingRecursive {

    public static int process(Stack<Integer> s) {
        int a = s.pop();
        if (s.isEmpty()) {
            return a;
        }
        int b = process(s);
        s.push(a);
        return b;
    }

    public static void reverse(Stack<Integer> s, int n, int size) {
        if (n == size) {
            return;
        }
        int a = process(s);
        reverse(s, n + 1, size);
        s.push(a);
    }

    public static void main(String[] args) {
        Stack<Integer> test = new Stack<Integer>();
        test.push(1);
        test.push(2);
        test.push(3);
        test.push(4);
        test.push(5);
        reverse(test, 0, test.size());
        System.out.println(test);
    }
}

題目八

給你一個二維陣列,二維陣列中的每個數都是正數,要求從左上角走到右下角,每一步只能向右或者向下。沿途經過的數字要累加起來。返回最小的路徑和。

解答
動態規劃

題目九

給你一個數組arr,和一個整數aim。如果可以任意選擇arr中的數字,能不能累加得到aim,返回true或者false

題目十

給定兩個陣列w和v,兩個陣列長度相等,w[i]表示第i件商品的重量,v[i]表示第i件商品的價值。 再給定一個整數bag,要求你挑選商品的重量加起來一定不能超 過bag,返回滿足這個條件下,你能獲得的最大價值。