其他分享
首页 > 其他分享> > 动态规划的简单进阶

动态规划的简单进阶

作者:互联网

剑指 Offer 49. 丑数

我们把只包含质因子 2、3 和 5 的数称作丑数

该句话的意思是这个数的质因子只能有2,3,5.因而进行数学推广可以得知大数值的丑数一定是某一个丑数的2,3,5的倍数,抽象成动态规划的状态转移方程为:dp[i]=dp[x]*2/3/5.

该题的难点在于得知初始状态是1的情况下如何进行状态转移不遗漏掉数,方法为使用a,b,c三个指针来确定2,3,5×过的数在dp数组中的位置。

(理解为一个丑数可以推广为三个丑数,分别是×2,3,5,这是由性质得到的。我们每次去ax2,bx3,cx5,并且取三个结果的最小数,再进行判断是abc哪个推广到当前位的丑数了,对其进行加一)

状态定义:dp[i]为当前第i位的丑数

状态转移:dp[i] = Math.min(dp[a]*2,dp[b]*3,dp[c]*5)

初始状态:dp[0] = 1

返回值:dp[n-1]

code:

/**
 * @param {number} n
 * @return {number}
 */
var nthUglyNumber = function(n) {
    var dp = [1];
    var a=0,b=0,c=0;
    for(i = 1;i<n;i++){
        var temp = Math.min(dp[a]*2,dp[b]*3,dp[c]*5);//取最小值来保证丑数紧跟顺序
        dp[i] = temp;
        if(dp[a]*2 == dp[i])a++;//因为已经被乘过丑数的某个质因子,因而索引加一,保证生成的丑数永远是新的,
        if(dp[b]*3 == dp[i])b++;
        if(dp[c]*5 == dp[i])c++;
    }
    return dp[n-1];
};

剑指 Offer 14- II. 剪绳子 II

该题有两种解法,时间复杂度最低的为贪心算法,也可以使用dp求解,参考剪绳子1

贪心算法的思想是因为经过数学计算发现我们可以永远在能剪3的情况下剪3,最后留下4则剪两个2,

code:

/**
 * @param {number} n
 * @return {number}
 */
var cuttingRope = function(n) {
    var res = 1;
    if(n==2)return 1;
    else if(n==3)return 2;
    while(n>4){
        n-=3;
        res=3*res %1000000007;
    }
    return (res*n) %1000000007
};

​​​​​​剑指 Offer 60. n个骰子的点数

该题进行动态规划求解的前提是进行数学讨论

Picture3.png

 可以看出fn是可以由n-1来进行得出的,得出方法是新建一个属于fn的所有可能性的数组并且覆盖为0,

每次n-1的每一位值×六次1/6,添加到fn的数组当中。

详细看代码注释

code:

/**
 * @param {number} n
 * @return {number[]}
 */
var dicesProbability = function(n) {
    var dp = new Array(6).fill(1/6);//dp[1]的初始数组
    for(var i=2;i<=n;i++){//循环求解当n为何值时的结果
        var temp = new Array(5*i+1).fill(0)//建立i的所有结果数组大小(5*i+1为推广得来,6*i-(i-1))
        for(var j=0;j<dp.length;j++){
            for(var k=0;k<6;k++){
                temp[j+k] += dp[j]/6//对n的数组进行循环赋值操作,每次操做上一个结果的六次x1/6
            }
        }
        dp = temp;
    }
    return dp;
};

 

标签:丑数,return,进阶,res,number,var,动态,规划,dp
来源: https://blog.csdn.net/weixin_46104231/article/details/121411308