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));
        }
    }
  • 相关阅读:
    C++中整型变量的存储大小和范围
    A1038 Recover the Smallest Number (30 分)
    A1067 Sort with Swap(0, i) (25 分)
    A1037 Magic Coupon (25 分)
    A1033 To Fill or Not to Fill (25 分)
    A1070 Mooncake (25 分)
    js 获取控件
    C#代码对SQL数据库添加表或者视图
    JS 动态操作表格
    jQuery取得下拉框选择的文本与值
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/12023454.html
Copyright © 2011-2022 走看看