算法题--动态规划(连续子数组的最大和、丑数、n个骰子的点数)

目录

动态规划

JS构建二维数组注意

题目

连续子数组的最大和

原题链接

解析

核心思想

答案

丑数

原题链接

解析

核心思想

答案

n个骰子的点数

原题链接

解析

核心思想

答案


动态规划

通常用于优化递归或求最大、最小值等问题。一般把结果存在一个数组中.

首先确定初始值res[0]=f(0),然后找到上下层res[i]和res[i+1]的关系,通过for循环递归解出arr[n]的值,找上下层关系的时候可以去列举res[0],res[1],res[2]...列举初始的前几位,找到对应的关系。

需要注意

  • 上下层的关系不一定是相差1,例如背包问题,相差arr[j](目标数组中的值);
  • 最大、最小值等问题可能需要涉及存储一些临时值用来跟res[i]判断大小后取。

JS构建二维数组注意

JavaScript构建2维数组的时候需要谨慎使用fill和map函数。正确的构建5*5全为0的数组使用

new Array(5).fill(0).map(v=>new Array(5).fill(0))。

错误的构建方式

1.使用new Array(5).map(v=>new Array(5).fill(0))相当于new Array(5),因为map不会对值为empty的数值返回内容。

2.new Array(5).fill(new Array(5).fill(0)),此时的arr[0]和arr[1~4]都是指向相同的引用,也就是说改变数组中一个值,其余4个值都会变为相同的,即fill填充的如果不是基础值,填充的会是相同的引用。

题目

连续子数组的最大和

输入一个长度为n的整型数组array,数组中的一个或连续多个整数组成一个子数组,子数组最小长度为1。求所有子数组的和的最大值。

输入:[1,-2,3,10,-4,7,2,-5]

返回值:18

经分析可知,输入数组的子数组[3,10,-4,7,2]可以求得最大和为18

输入:[2]

返回值:2

输入:[-10]

返回值:-10

原题链接

连续子数组的最大和_牛客题霸_牛客网

解析

这里需要注意要有一个变量存储,之前一个最大连续的子数组一直加上到i位元素的和。例如输入[1,-2,3,10,-4,7,2,-5]时,当计算到-4时,计算是否加上7时,该变量应该存储3+10+-4,这时用3+10+-4+7和3+10和7这3位对比选取最大。

核心思想

首先找到初始值res[0]=arr[0],然后找到上下层级的关系。这里需要分析以下例如下面3个数组,[-1,100],[-10,100,40,80,-20,200]、[-1,-10],我们什么时候需要把下一个算进去,什么时候需要重新开始计算。

结论:res[i+1]=Math.max(res[i],tmp+arr[i+1],arr[i+1],) tmp为记录之前的一个最大连续子数组一直加上到目前i位元素的和。

答案

function FindGreatestSumOfSubArray(array) {
	let temp = array[0]
	let res = new Array(array.length).fill(0)
	res[0] = array[0]
	for (let i = 1; i < array.length; i++) {
		temp = Math.max(array[i], array[i] + temp)
		res[i] = Math.max(temp, res[i - 1])
	}
	return res.pop()
}

丑数

我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

示例:

输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

说明:  

  1. 1 是丑数。
var nthUglyNumber = function(n) {

};

原题链接

力扣

解析

注意题目要求要只能被2,3,5整除,14被2整除后是7,不算。

最小堆的解法见原题链接

核心思想

假如res[n]表示第n为丑数,因为只能被2,3,5整除,那么res[n]必然为2*res[m]或者3*res[m]或者5*res[m]其中一个,此时便可以用动态规划,

初始值,res[1]=1,

找上下层的关系res[2]=Math.min(res[1]*2,res[1]*3,res[1]*5)

res[3]=Math.min(res[2]*2,res[1]*3,res[1]*5)

总结:res[n]=Math.min( res[p2] * 2, res[p3] * 3, res[p5] * 5),p2,p3,p5每次取完后需要递增。

答案

var nthUglyNumber = function(n) {
    const res = new Array(n + 1).fill(0);
    res[1] = 1;
    let p2 = 1, p3 = 1, p5 = 1;
    for (let i = 2; i <= n; i++) {
        const num2 = res[p2] * 2, num3 = res[p3] * 3, num5 = res[p5] * 5;
        res[i] = Math.min(num2, num3, num5);
        if (res[i] === num2) {
            p2++;
        }
        if (res[i] === num3) {
            p3++;
        }
        if (res[i] === num5) {
            p5++;
        }
    }
    return res[n];
};

n个骰子的点数

把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。

你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。

示例 1:

输入: 1
输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]

示例 2:

输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]
var dicesProbability = function(n) {

};

原题链接

力扣

解析

思考骰子的添加对点数概率的影响。

核心思想

1个骰子时,每个点数的组合数为[1,1,1,1,1,1],概率在组合数上除以6,添加一个骰子,点数为2~12,每个点数的组合数为少一个骰子的组合数加1~6,例如点数5为1+4,2+3,3+2,4+1,即组合数的和为4。得出所有组合数为[1,2,3,4,5,6,5,4,3,2,1],概率为除以6*6,再加一个骰子,点数为3~18,每个点数的组合数为少一个骰子的组合数加1~6。

[1,2,3,4,5,6,5,4,3,2,1]

   [1,2,3,4,5,6,5,4,3,2,1]

      [1,2,3,4,5,6,5,4,3,2,1]

         [1,2,3,4,5,6,5,4,3,2,1]

            [1,2,3,4,5,6,5,4,3,2,1]

               [1,2,3,4,5,6,5,4,3,2,1]

=[1,3,6,10,15,21,25,27,27,25,21,15,10,6,3,1]

以此类推。

答案

function nums(n){
    if(n===1){
        return [1,1,1,1,1,1]
    }else {
        let arr = nums(n-1), re =Array(5*n+1).fill(0);
        for(let i=0;i<6;i++){
            for(let j=0;jitem/(6**n));
};

你可能感兴趣的:(算法,动态规划算法解题,算法题连续子数组的最大和,算法题丑数,算法题n个骰子的点数,JavaScript解算法题)