zoukankan      html  css  js  c++  java
  • 动态规划学习之LeetCode分割整数相关题目(第343、279、91题)

    题目:给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

    示例:

    输入: 10
    输出: 36
    解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

    说明: 你可以假设 不小于 2 且不大于 58。

    分析:

      1.定义一个状态转移数组dp,dp[i]表示数字i拆分为至少两项之和后,拆分后的数字之间的最大乘积。

      2.寻找关系式,那么如何确定dp[i]的最大值呢?首先我们要确定它有哪些取值的可能,对于拆分之和的数字的乘积,这个乘积可能是两个数字的乘积,也可能是多个数字之间的乘积,那么如何表示这两种乘积呢?

        1)对于两个数的乘积,就是一个小于i的数j,和i-j之间的乘积,即 (i - j)* j;

        2)对于多个数之间的乘积,就是相当于一个小于i的数j,和dp[i-j]的乘积,即 j * dp[i-j] ;

      3.初始条件,根据题目,n从2开始,多以dp[2] = 1;

      4.需要借助于双层循环,外层循环从3开始,到n结束,因此状态转移数组的空间大小是n+1,内层循环是为了寻找当前i的最大拆分数字之积

    首先的代码如下:

        public int integerBreak(int n) {
            if (n==2)
                return 1;
            int[] dp = new int[n+1];
            dp[2] = 1;
    
            for (int i = 3; i <= n ; i++) {
                for (int j = 1; j < i; j++) {
                    dp[i] = Math.max(Math.max(dp[i],j*(i-j)),j*dp[i-j]);
                }
            }
            return dp[n];
        }

    题目:给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

    示例:

    输入: n = 12
    输出: 3 
    解释: 12 = 4 + 4 + 4.

    分析:这个题的解决思路和上面那个题的解决思路相似,具体流程如下:

      1.定义一个状态转移数组dp,dp[i]表示数字i由完全平方数组成的最少个数;

      2.寻找关系式,如果i本身就是一个完全平方数,那么这就是最理想的情况了,dp[i]的值直接为1;如果不是,那么就需要从小于1~i-1的数字中去寻找了,那么此时dp[i] = dp[j] + dp[i-j],即i拆分为j和i-j,二者的最少个数,就是i的最少个数。

      3.初始值,外层循环是从1开始遍历,到n结束,因此dp[1] = 1,内层循环用于寻找当前遍历的数字i的拥有完全平方数的最少个数,如果i不是完全平方数字,那么在i自己寻找之前,dp[i]设置为一个最大值。

    实现代码:

        public int numSquares(int n) {
            if ((int) Math.sqrt(n) - Math.sqrt(n) == 0){
                return 1;
            }
            int[] dp = new int[n+1];
            dp[1] = 1;
    
            for (int i = 2; i <= n; i++) {
                if ((int) Math.sqrt(i) - Math.sqrt(i) == 0){
                    dp[i] = 1;
                }else {
                    dp[i] = Integer.MAX_VALUE;
                    for (int j = 1; j < i; j++) {
                        dp[i] = Math.min(dp[i],dp[j] + dp[i-j]);
                    }
                }
            }
            return dp[n];
        }

    题目:一条包含字母 A-Z 的消息通过以下方式进行了编码:

    'A' -> 1
    'B' -> 2
    ...
    'Z' -> 26

    给定一个只包含数字的非空字符串,请计算解码方法的总数。

    示例:

    输入: "12"
    输出: 2
    解释: 它可以解码为 "AB"(1 2)或者 "L"(12)

    分析:对于给定的一串数字,能够正确的解码的前提条件是,这个数字或者它和它前面的一个数字组成的两位数字位于1~26之间,否则都是不能被正确解码的,具体的过程如下:

      1.定义一个数组dp,dp[i]表示前i个字符构成的子串所拥有的解码方法的总数;

      2.寻找关系式:对于能够解码的情况有两种:

        一种是,对于当前遍历的这个字符,被用于单独解码,它只要大于'0',那么就能够被解码,在它被用来单独解码的时候,它的前i-1个字符构成的子串的解码方法总数是不变的,也就是相当于在前i-1个字符构成的子串末尾增加一个单独编码的字符,并不会影响整体编码,它们的解码方法总数一致;

        另一种是,对于当前遍历的这个字符,不是被用于单独编码的,它被用来和它的前一个字符组成一个二位数,如果这个二位数在10~26之间,对于这种的组合编码的情况下,前i个字符构成的子串含有的解码方法总数是和它的前i-2个字符构成的子串的解码方法总数是一致的,即在前i-2个字符构成的子串的末尾加上一个组合编码数,并不会影响前i-2字符的解码情况。

        这两个情况需要逐一判断,才不会漏掉所有的解码方法

      3.初始值,dp[0] = 1,dp[1] = 1,这里d[1]代表字符串的第一个字符,dp[0]没有实际的含义,只是充当一个数字1存在,此处设置dp[0]为1,纯粹是为了i=1时:

      第i个字符和第i-1个字符能够构成合法解码数字的时候,使解码方法总数加1。因为此时子串的总个数是2,比如226,子串22解码个数包括2、2和22。为22的时候,相对于dp[2]的值,应该是dp[1]的值再加上1,因为22也构成了一个解码方法,而dp[0]并没有对应的子字符串,所以用来当做一个1。

    实现代码:

        public int numDecodings(String s) {
            if (s.charAt(0)=='0')
                return 0;
            if (s.length()==1&&s.charAt(0) > '0')
                return 1;
            int n = s.length();
            int[] dp = new int[s.length()+1];
            dp[0] = 1;
            dp[1] = 1;
            for (int i = 1; i < n; i++) {
                int two_nums = s.charAt(i) - '0' + (s.charAt(i-1) -'0')*10;
                if (s.charAt(i) > '0')
                    dp[i+1] = dp[i];
                if (two_nums > 9 && two_nums <=26)
                    dp[i+1] += dp[i-1];
                if (dp[i+1]==0)
                    return 0;
            }
            return dp[n];
        }

    一定要根据题目的要求找清楚数组元素之间的推导关系!!!

  • 相关阅读:
    内网穿透(Frp)-拯救没有公网IP的你
    用Windows远程桌面连接树莓派的方法
    TensorFlow 1.9开始支持树莓派
    树莓派制作遥控小车-新手教程
    Layui 一个页面包含多个table时不展示分页条
    MVC 通过@符号把数据赋值给jQuery对象
    jQuery 批量为表单元素赋值
    layui分页组件,一直在调用方法的解决办法
    layui 表格复选框不居中解决办法
    JQuery 解决遮罩层下内容可以滚动问题
  • 原文地址:https://www.cnblogs.com/yxym2016/p/12641507.html
Copyright © 2011-2022 走看看