7、深入递归,DFS(深度搜索),回溯,剪枝

"逐步生成结果"类问题之数值型

自上而下 --递归

自下而上 --递推,数学归纳,动态规划

1、先解决简单下的问题
2、然后推广到复杂项的问题
3、如果递推次数很明确,最好用迭代(即从开始,一步一步往后推)
4、如果有封闭形式,可以直接求解

题1:爬楼梯问题

三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。
思考一下,小孩最后迈出了多少步?
小孩上楼梯的最后一步,就是抵达第n 阶的那一步,迈过的台阶数可以是3、2 或者1。
那么小孩有多少种方法走到第n 阶台阶呢?目前还不知道,但我们可以把它与一些子问题联系起来。
到第n 阶台阶的所有路径,可以建立在前面3 步路径的基础之上。我们可以通过以下任意方式走到第n 阶台阶。
 在第n-1 处往上迈1 步。
 在第n-2 处往上迈2 步。
 在第n-3 处往上迈3 步。
因此,我们只需把这3 种方式的路径数相加即可。
这里要非常小心,有很多人会把它们相乘。相乘应该是走完一个再走另一个,显然和以上
情况不符。

采取两种方法,一种是迭代,一种是递推
递推

public static int kind(int n){
   
    if(n==1){
   
        return 1;
    }else if(n==2){
   
        return 2;
    }else if(n==3){
   
        return 4;
    }else{
   
        int x1=1;
        int x2=2;
        int x3=4;
        for(int i=0;i<n-3;i++ ){
   
            int t=x1;
            x1=x2;
            x2=x3;
            x3=x1+x2+t;
        }
        return x3%1000000007;
    }

迭代

public static int kind(int n){
   
    if(n==1){
   
        return 1;
    }else if(n==2){
   
        return 2;
    }else if(n==3){
   
        return 4;
    }else{
   
        return kind(n-1)+kind(n-2)+kind(n-3);
    }
题2:机器人走方格

有一个XxY的网有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。
给定两个正整数int x,int y,请返回机器人的走法数目。保证x+y小于等于12格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。请设计一个算法,计算机器人有多少种走法。
给定两个正整数int x,int y,请返回机器人的走法数目。保证x+y小于等于12。
先不断在小范围内发现规律,在求解新问题时尽可能用到原来求的,得到新问题的答案

public static int fun(int x,int y){
   
    int [][]m=new int[x+1][y+1];
    for(int i=1;i<=x;i++){
   
        m[i][1]=1;
    }
    for(int i=1;i<=y;i++){
   
        m[1][i]=1;
    }
    for(int i=2;i<=x;i++){
   
        for(int j=2;j<=y;j++){
   
            m[i][j]=m[i][j-1]+m[i-1][j];
        }
    }
    return m[x][y];
}
题3:硬币

"逐步生成结果"类问题之非数值型

对于非数值型,此时就要用容器来装了
生成一点,装一点,所谓迭代就是慢慢改变
此时就需要用到容器的知识了
Set为集合,可自动消除重复的元素,并且没有下标,只能用for-each进行遍历
List为表,有下标

题1:括号

括号。设计一种算法,打印n对括号的所有合法的(例如,开闭一一对应)组合。
说明:解集不能包含重复的子集。
例如,给出 n = 3,生成结果为:
[ “((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”]

递归

public static Set<String> fun(int n){
   
    Set<String> s_n=new HashSet<>();
    if(n==1){
   
        s_n.add("()");
    }
    else {
   
        Set<String> s_n_1 = fun(n - 1);
        for (String s : s_n_1) {
   
            s_n.add("()" + s);
            s_n.add("(" + s + ")");
            s_n.add(s + "()");
        }
    }
    return s_n;
}

迭代

public static Set<String> fun(int n){
   
    Set<String> res=new HashSet<>();//保留上次迭代的状态
        res.add("()");
        if(n==1){
   
            return res;
        }
        for(int i=2;i<=n;i++){
   
            Set<String> res_new=new HashSet<>();
            for(String s:res) {
   
                res_new.add("()" + s);
                res_new.add("(" + s + ")");
                res_new.add(s + "()");
                res = res_new;
            }
        }
        return res;

    }
题2:幂级

幂集。编写一种方法,返回某集合的所有子集。集合中不包含重复的元素。
说明:解集不能包含重复的子集。
7、深入递归,DFS(深度搜索),回溯,剪枝_第1张图片

初步生成 迭代大法
public static Set<Set<Integer>> fun(int []A,int n){
   
    Set<Set<Integer>> res=new HashSet<>();
    res

你可能感兴趣的:(算法)