美文网首页
算法模式--动态规划(dynamic programming)

算法模式--动态规划(dynamic programming)

作者: 牛油果大虾 | 来源:发表于2020-03-09 23:13 被阅读0次
动态规划是一种将复杂问题分解成更小的相互依赖的子问题来解决的优化技术

关键点:创建dp数组

1. 最小路径和

//给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
        // 说明:每次只能向下或者向右移动一步。
        // 示例:
        // 输入:
        // [
        //   [1,3,1],
        //   [1,5,1],
        //   [4,2,1]
        // ]
        // 输出: 7
        // 解释: 因为路径 1→3→1→1→1 的总和最小。
        //难度:中等
//解题思想:拆分成小问题算出到达每个子位置的最小路径和
        var minPathSum = function (grid) {
            var m = grid.length;
            var n = grid[0].length;
            var dp = Array.from({ length: grid.length }, item => item = []);
            for (var i = 0; i < m; i++) {
                for (var j = 0; j < n; j++) {
                    if (i === 0 && j === 0) {
                        dp[i][j] = grid[i][j]
                    } else if (i === 0 && j !== 0) {
                        dp[i][j] = grid[i][j] + dp[i][j - 1]
                    } else if (i !== 0 && j === 0) {
                        dp[i][j] = grid[i][j] + dp[i - 1][j]
                    } else {
                        dp[i][j] = Math.min(grid[i][j] + dp[i][j - 1], grid[i][j] + dp[i - 1][j])
                    }
                }
            }
            return dp[m - 1][n - 1]
        };

2.打家劫舍

//         你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
        // 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
        // 示例 1:
        // 输入: [1,2,3,1]
        // 输出: 4
        // 解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
        //      偷窃到的最高金额 = 1 + 3 = 4 。
      //难度:中等
      //解题思想: 根据3次以内的情况得到计算方程
        var rob = function (nums) {
            if (nums.length === 0) return 0;
            //dp dynamic programming 动态规划简写
            var dp = [];
            dp[0] = 0;
            dp[1] = nums[0];
            for (var i = 2; i <= nums.length; i++) {
                dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i - 1]);
            }
            return dp.pop();
        };

3.乘积最大子序列

 // 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。
        // 示例 1:
        // 输入: [2,3,-2,4]
        // 输出: 6
        // 解释: 子数组 [2,3] 有最大乘积 6。
        // 示例 2:
        // 输入: [-2,0,-1]
        // 输出: 0
        // 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
        var maxProduct = function (nums) {
            if (nums.length === 0) return 0;
            //1.设置初始默认最大值,及默认乘积最大值,因为涉及负数最小值,当遇到负数时,最大和最小会互换,所以设置保存最小乘积变量.
            let max = nums[0], imax = 1, imin = 1;
            for (let i = 0; i < nums.length; i++) {
                if (nums[i] < 0) [imax, imin] = [imin, imax];
                imax = Math.max(imax * nums[i], nums[i]);
                imin = Math.min(imin * nums[i], nums[i]);
                max = max > imax ? max : imax;
            }
            return max;
        };

4. 最少硬币找零

//给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
// 示例 1:
// 输入: coins = [1, 2, 5], amount = 11
// 输出: 3 
// 解释: 11 = 5 + 5 + 1
// 示例 2:
// 输入: coins = [2], amount = 3
// 输出: -1
//解题思路:所要金额可用amount减去coins中任一面值+1得到
//例如amount = 15,coins=[1,2,11,15],可由f(amount-coin)+1得到,即f(0)+1,f(4)+1,f(13)+1,f(14)+1
var coinsChange = function(amount,coins){
    let dp = Array.from({length: amount+1},item=>item=Infinity);
    dp[0] = 0;
    for(var i=1;i<=amount;i++){
        for(var coin of coins){
            console.log(dp)
            if(i-coin>=0){
                //i=1时,dp[1]=dp[0]+1=1
                dp[i] = Math.min(dp[i],dp[i-coin]+1)
            }
        }
    }
    return dp[amount]===Infinity?-1:dp[amount]
}

console.log(coinsChange(16,[1,2,5]))

5. 最长公共子序列

 //     给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列。
        // 一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
        // 例如,"ace" 是 "abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。
        // 若这两个字符串没有公共子序列,则返回 0。
        // 示例 1:
        // 输入:text1 = "abcde", text2 = "ace" 
        // 输出:3  
        // 解释:最长公共子序列是 "ace",它的长度为 3。
        // 示例 2:
        // 输入:text1 = "abc", text2 = "abc"
        // 输出:3
        // 解释:最长公共子序列是 "abc",它的长度为 3。
        // 示例 3:
        // 输入:text1 = "abc", text2 = "def"
        // 输出:0
        // 解释:两个字符串没有公共子序列,返回 0
        解题思路:列出一个二维dy数组,列出每个位置子序列长度
        var longestCommonSubsequence = function (text1, text2) {
            var m = text1.length,//rows
                n = text2.length, //cols
                dp = Array.from({ length: n + 1 }, item => item = new Array(m + 1).fill(-Infinity));
            dp[0][0] = 0;
            for (var i = 0; i <= n; i++) {
                for (var j = 0; j <= m; j++) {
                    if (i === 0 || j === 0) {//有一方为0结论为0
                        dp[i][j] = 0
                    } else if (text1[j-1] === text2[i-1]) {//i,j对应字符相等
                        dp[i][j] = dp[i - 1][j - 1] + 1
                    } else {
                        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                    }
                }
            }
            return dp[n][m];
        };

相关文章

  • 动态规划

    算法-动态规划 Dynamic Programming

  • 程序设计的16种类型

    Dynamic Programming(动态规划) Greedy(贪心算法) Complete Search(穷举...

  • 动态规划

    动态规划(Dynamic Programming) 本文包括: 动态规划定义 状态转移方程 动态规划算法步骤 最长...

  • 算法模式--动态规划(dynamic programming)

    动态规划是一种将复杂问题分解成更小的相互依赖的子问题来解决的优化技术 关键点:创建dp数组 1. 最小路径和 2....

  • 动态规划算法

    动态规划(Dynamic Programming,DP)是算法设计思想中最难也是最有趣的部分。掌握动态规划算法,对...

  • 动态规划算法之解决背包问题

    动态规划算法介绍 动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题进行解决...

  • 带你入门动态规划算法

    一、导论  动态规划(Dynamic Programming,DP)是算法设计思想中最难也是最有趣的部分。掌握动态...

  • 动态规划套路

    动态规划 动态规划(dynamic programming,简称 dp),是一类求解最优值的算法。有一定的套路可以...

  • 动态规划

    概念 动态规划(Dynamic Programming),是一种分阶段求解的方法。动态规划算法是通过拆分问题,定义...

  • 动态规划

    概述 Dynamic Programming => 动态规划 Programming => 制表法 Fibonac...

网友评论

      本文标题:算法模式--动态规划(dynamic programming)

      本文链接:https://www.haomeiwen.com/subject/jqvpdhtx.html