• 常用算法解析-动态规划


     1 import java.util.HashMap;
     2 
     3 /**
     4  * 
     5  *原文链接: https://wx.abbao.cn/a/4736-4b66e5f9ec584ee0.html
     6  * 
     7  * 走楼梯问题:有一座高度是10级台阶的楼梯,从下往上走,每跨一步只能向上1级或者2级台阶。要求用程序来求出一共有多少种走法。
     8  * 
     9  * 這是一道入门级的动态递归问题
    10  * 
    11  * 问题分析:
    12  * 
    13  * 最有子结构: 最后一步走到第十层有多少种方法?2种:8-》10;9-》10 那么如果走到 8 有x种情况,走到9有y中情况 走到10可以看成x+y
    14  * 
    15  * 状态转移方程 若用公式表达f(10)=f(9)+f(8) 既 f(n) = f(n-1) + f(n-2)
    16  * 
    17  * 边界 走到第二层可以走一步,也可以走俩步。即f(2) = 2 第一层只能走一步 f(1) =1
    18  * 
    19  * 以上是问题建模 解析来是问题求解
    20  */
    21 public class WalkStair {
    22     public static void main(String[] args) {
    23         System.out.println(getWayStair1(10));
    24         System.out.println(getWayStair2(10, new HashMap<Integer, Integer>()));
    25         System.out.println(getWayStair3(10));
    26     }
    27 
    28     /**
    29      * 第一种思路:用递归的方式
    30      * 
    31      * @param n n层楼梯
    32      * 
    33      *          这里需要注意一下复杂度问题 这个二叉树长度n-1,节点2^n-1,时间复杂度2^n
    34      */
    35     public static int getWayStair1(int n) {
    36         if (n == 1) {
    37             return 1;
    38         }
    39         if (n == 2) {
    40             return 2;
    41         }
    42         return getWayStair1(n - 1) + getWayStair1(n - 2);
    43     }
    44 
    45     /**
    46      * 第二种思路:还是递归,但是重复的计算几点可以不在计算,叫做备忘录算法 利用map将已经计算过的节点保存
    47      * 
    48      * 时间复杂度是 o(n)
    49      * 
    50      * @param n
    51      * @param map
    52      * @return
    53      */
    54     public static int getWayStair2(int n, HashMap<Integer, Integer> map) {
    55         if (n == 1) {
    56             return 1;
    57         }
    58         if (n == 2) {
    59             return 2;
    60         }
    61         if (map.containsKey(n)) {
    62             return map.get(n);
    63         } else {
    64             int value = getWayStair1(n - 1) + getWayStair1(n - 2);
    65             map.put(n, value);
    66             return value;
    67         }
    68     }
    69 
    70     /**
    71      * 第三种思路:动态规划,每次得到的结果只是上俩次结果的和 时间复杂度o(n) 空间复杂度o(1)
    72      * 
    73      * @param n
    74      * @return
    75      */
    76     public static int getWayStair3(int n) {
    77         if (n == 0) {
    78             return 0;
    79         }
    80         if (n == 1) {
    81             return 1;
    82         }
    83         if (n == 2) {
    84             return 2;
    85         }
    86 
    87         int a = 1;
    88         int b = 2;
    89         int temp = 0;
    90         for (int i = 3; i <= n; i++) {
    91             temp = a + b;
    92             a = b;
    93             b = temp;
    94         }
    95         return temp;
    96     }
    97 }
     1 /**
     2  * 问题描述:十个人挖五座金矿,求挖到的最多的金子个数
     3  * 
     4  * 思路: 最优子结构: ‘1:第五座金矿挖 ’2:第五座金矿不挖 边界: ‘1:挖一座金矿 人数够 ’2:挖一座金矿人数不够 状态转移方程
     5  *
     6  */
     7 public class GoldMiner {
     8     /**
     9      * 
    10      * @param n 前 n 座矿
    11      * @param w 工人个数
    12      * @param p 每座矿需要的工人个数
    13      * @param g 每座矿的金子个数
    14      * @return
    15      */
    16     public static int getMaxGold(int n, int w, int p[], int g[]) {
    17 
    18         // ‘前三个if是边界值
    19         if (n < 1) {
    20             return 0;
    21         }
    22         if (n == 1 && w < p[0]) {
    23             return 0;
    24         }
    25         if (n == 1 && w >= p[0]) {
    26             return g[0];
    27         }
    28 
    29         // ’这里是初始化结果
    30         int[] preResult = new int[w + 1];
    31         int[] result = new int[w + 1];
    32         for (int i = 0; i < w; i++) {
    33             if (w >= p[0]) {
    34                 preResult[i] = g[0];
    35             } else {
    36                 preResult[i] = 0;
    37             }
    38         }
    39 
    40         /**
    41          * ‘外层循环控制挖第几座金矿,内层第一层循环控制可能挖的最优结果,内层第二层循环刷新可能获得最优结果,最後返回當前人人数能挖的最优结果
    42          */
    43         for (int i = 0; i < n; i++) {
    44             for (int j = 0; j <= w; j++) {
    45                 if (j < p[i]) {
    46                     result[j] = preResult[j];
    47                 } else {
    48                     result[j] = Math.max(preResult[j], preResult[j - p[i]] + g[i]);
    49                 }
    50             }
    51             for (int j = 0; j <= w; j++) {
    52                 preResult[j] = result[j];
    53             }
    54         }
    55         return result[w];
    56     }
    57 
    58     public static void main(String[] args) {
    59         int[] g = { 400, 500, 200, 300, 350 };
    60         int[] p = { 5, 5, 3, 4, 3 };
    61         System.out.println(getMaxGold(5, 10, p, g));
    62     }
    63 }
     1 import java.util.ArrayList;
     2 import java.util.List;
     3 
     4 /**
     5  * 问题:
     6  * Given a non-empty string s and a dictionary wordDict containing a list of
     7  * non-empty words, determine if s can be segmented into a space-separated
     8  * sequence of one or more dictionary words.
     9  *
    10  */
    11 public class Lc139 {
    12     /**
    13      * 思路:dp 上一个串的位置到当前截取串的位置恰好是一个字典串
    14      * @param s
    15      * @param wordDict
    16      * @return
    17      */
    18     public static boolean wordBreak(String s, List<String> wordDict) {
    19         boolean[] dp = new boolean[s.length() + 1];
    20         dp[0] = true;
    21 
    22         for (int i = 1; i < dp.length; i++) {
    23             for (int j = 0; j < i; j++) {
    24                 if (true == dp[j] && wordDict.contains(s.substring(j, i))) {
    25                     dp[i] = true;
    26                 }
    27             }
    28         }
    29         return dp[s.length()];
    30     }
    31 
    32     public static void main(String[] args) {
    33         String s = "leetcode";
    34         String s1 = "leet";
    35         String s2 = "code";
    36         List<String> wordDict = new ArrayList<String>();
    37         wordDict.add(s1);
    38         wordDict.add(s2);
    39         System.out.println(wordBreak(s, wordDict));
    40     }
    41 }
  • 相关阅读:
    TFS 服务器更换后工作区无法绑定
    导出你的GAC Assembly中的DLLS
    MICROSOFT REPORT VIEWER 2012之无法加载相关的dll
    查询可用的Nuget服务地址
    认识k_BackingField【转】
    EntityFramework 中生成的类加注释
    Bat命令知识[转]
    利用bat批量执行脚本文件
    SQL Server 2012 LocalDB 管理之旅
    【转】Windows环境下.NET 操作Oracle问题
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/11800080.html
Copyright © 2020-2023  润新知