zoukankan      html  css  js  c++  java
  • leetcode-dp

    参考文章

    https://blog.csdn.net/u013309870/article/details/75193592
    https://blog.csdn.net/baidu_28312631/article/details/47418773

    动态规划

    凡是可以大事化小的都可以用动态规划
    一般解题步骤:找出最优子结构,找到状态转移方程,找到边界值

    动态规划和贪心算法的区别

    https://blog.csdn.net/weixin_39332529/article/details/89440114
    最大的区别:贪心是通过局部最优解推导全局最优解
              dp是通过所有的最优解推导全局最优解
    所以贪心算法推到的全局最优解未必正确

    dp常见题目

    第一道题目展示dp的优点,将阶时间复杂度
    import java.util.HashMap;
    import java.util.Map;

    /**
     * You are climbing a stair case. It takes n steps to reach to the top.
     * 
     * Each time you can either climb 1 or 2 steps. In how many distinct ways can
     * you climb to the top?
     * 
     * Note: Given n will be a positive integer.
     * 
     * Example 1:
     * 
     * Input: 2 Output: 2 Explanation: There are two ways to climb to the top. 1. 1
     * step + 1 step 2. 2 steps Example 2:
     * 
     * Input: 3 Output: 3 Explanation: There are three ways to climb to the top. 1.
     * 1 step + 1 step + 1 step 2. 1 step + 2 steps 3. 2 steps + 1 step
     *
     */

    public class Lc70 {
        /*
         * 递归: fn=fn-1+fn-2; f1=1 f2=2
         */

        public static int climbStairs(int n{
            if (n == 1) {
                return 1;
            }
            if (n == 2) {
                return 2;
            }
            return climbStairs(n - 1) + climbStairs(n - 2);
        }

        /*
         * 递归优化 备忘录
         */

        public static int climbStairs1(int n{
            if (n == 1) {
                return 1;
            }
            if (n == 2) {
                return 2;
            }
            Map<Integer, Integer> map = new HashMap<>();
            if (map.containsKey(n)) {
                return map.get(n);
            } else {
                int value = climbStairs1(n - 1) + climbStairs1(n - 2);
                map.put(n, value);
                return value;
            }

        }

        /**
         * 动态规划
         * 
         * 最优子结构:最后一步到顶点的步长? 状态转移方程: 若最后一步走一步,之前到最后一步为x种,若最后一步走俩步,则到最后一步有y中,那么到最后顶点为 x+y
         * 边界:f1=1; f2=2;
         * 
         * @param n
         * @return
         */

        public static int climbStairs2(int n{
            if (n == 1) {
                return 1;
            }
            if (n == 2) {
                return 2;
            }
            int a = 1;// ’走台阶1
            int b = 2;// ‘走台阶2

            for (int i = 3; i <= n; i++) {
                int temp = a + b;// 走当前台阶等于上一次加上上一次
                a = b;
                b = temp;
            }
            return b;
        }

        public static void main(String[] args{
            System.out.println(climbStairs(10));
            System.out.println(climbStairs1(10));
            System.out.println(climbStairs2(10));
        }
    }
    之后的题目展示dp常见的类型
    import java.util.Arrays;

    /**
     * Perfect Squares
     *
     */

    public class Lc279 {
        /**
         * dp 最优子结构:完全平方数个数等于 非完全平方数 + 1(完全平方数) 状态转移方程:dp[n] =
         * min(dp[a-x*x]+1,dp(a+x*x)) 边界值 所有的平方值为1
         */

        public static int numSquares(int n) {
            int[] dp = new int[n + 1];
            Arrays.fill(dp, Integer.MAX_VALUE);
            for (int i = 0; i * i <= n; i++) {
                dp[i * i] = 1;
            }
            for (int i = 0; i <= n; i++) {
                for (int j = 0; i + j * j <= n; j++) {
                    dp[i + j * j] = Math.min(dp[i + j * j], dp[i] + 1);
                }
            }
            return dp[n];
        }

        public static void main(String[] args) {
            System.out.println(numSquares(12));
        }
    }


    import java.util.ArrayList;
    import java.util.List;

    /**
     * 问题: Given a non-empty string s and a dictionary wordDict containing a list of
     * non-empty words, determine if s can be segmented into a space-separated
     * sequence of one or more dictionary words.
     *
     */

    public class Lc139 {
        /**
         * dp 最优子结构:若0到i截取的串可以匹配,若i到末尾也可以匹配则证明可以被串都匹配;
         * 
         * 状态转移方程:dp[i] = true
         * 
         * dp[j]= true dp[0] = true
         */

        public static boolean wordBreak(String s, List<String> wordDict) {
            int len = s.length();
            boolean[] dp = new boolean[len + 1];
            dp[0] = true;
            for (int i = 1; i <= len; i++) {
                for (int j = i - 1; j >= 0 && !dp[i]; j--) {
                    String str = s.substring(j, i);
                    dp[i] = dp[j] && wordDict.contains(str);
                }
            }
            return dp[len];

        }

        public static void main(String[] args) {
            String s = "leetcode";
            String s1 = "leet";
            String s2 = "code";
            List<String> wordDict = new ArrayList<String>();
            wordDict.add(s1);
            wordDict.add(s2);
            System.out.println(wordBreak(s, wordDict));
        }
    }


    这是dp找最大路径的模型
    /**
     * 数字三角形,求最大路径和
     *
     */

    public class LcMaxSum {
        public static int maxSum(int[][] array) {
            if (array == null) {
                return 0;
            }
            int row = array.length;

            int dp[] = array[row - 1];

            for (int i = row - 2; i >= 0; i--) {
                for (int j = 0; j < array[i].length; j++) {
                    dp[j] = Math.max(array[i][j] + dp[j], array[i][j] + dp[j + 1]);
                }
            }
            return dp[0];
        }

        public static void main(String[] args) {
            int[][] array = { { 1 }, { 23 }, { 456 } };
            System.out.println(maxSum(array));
        }
    }

    /**
     * You are a professional robber planning to rob houses along a street. Each
     * house has a certain amount of money stashed, the only constraint stopping you
     * from robbing each of them is that adjacent houses have security system
     * connected and it will automatically contact the police if two adjacent houses
     * were broken into on the same night.
     * 
     * Given a list of non-negative integers representing the amount of money of
     * each house, determine the maximum amount of money you can rob tonight without
     * alerting the police.
     */

    public class Lc198 {
        /*
         * 若dp[i]表示为当前最大值 则对于某个位置i ,存在取和不取,即dp[i-2]+num[i],dp[i-1]
         * 则状态转移方程max(dp[i-2]+num[i],dp[i-1])
         */

        public static int rob(int[] nums) {
            if (nums.length == 0) {
                return 0;
            }
            int dp[] = new int[nums.length];
            if (nums.length >= 1) {
                dp[0] = nums[0];
            }
            if (nums.length >= 2) {
                dp[1] = Math.max(nums[0], nums[1]);
            }
            if (nums.length >= 3) {
                for (int i = 2; i < nums.length; i++) {
                    dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
                }
            }

            return dp[nums.length - 1];

        }

        public static void main(String[] args) {
            int[] nums = { 2112 };
            System.out.println(rob(nums));
        }
    }
  • 相关阅读:
    左偏树初识到应用
    Linux用户管理简介
    Linux命令(二十五) 磁盘管理命令(三) fdisk
    Linux命令(二十四) 磁盘管理命令(二) mkfs,mount
    Linux命令(二十三) 磁盘管理命令(一) df,du,tune2fs
    操作系统学习(十四) 、中断描述符表和中断描述符
    操作系统学习(十三) 、中断和异常
    操作系统学习(十二) 、页级保护
    使用Ubuntu编译Linux内核
    操作系统学习(十一) 、一致代码段和非一致代码段
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/12023454.html
Copyright © 2011-2022 走看看