动态规划

前言


粉刷房子_简单

普通的动态方程dp[i] = dp[i-1] + xx不满足条件
如:[[4,5,13],[1,100,1000]]
所以对于每个粉刷的值由其本身和上个房子的两种颜色决定。

假如有一排房子,共 n
个,每个房子可以被粉刷成红色、蓝色或者绿色这三种颜色中的一种,你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。
当然,因为市场上不同颜色油漆的价格不同,所以房子粉刷成不同颜色的花费成本也是不同的。每个房子粉刷成不同颜色的花费是以一个 n x 3
的矩阵来表示的。
例如,costs[0][0] 表示第 0 号房子粉刷成红色的成本花费;costs[1][2] 表示第 1
号房子粉刷成绿色的花费,以此类推。请你计算出粉刷完所有房子最少的花费成本。
注意:
所有花费均为正整数。
示例:
输入: [[17,2,17],[16,16,5],[14,3,19]] 输出: 10 解释: 将 0 号房子粉刷成蓝色,1
号房子粉刷成绿色,2 号房子粉刷成蓝色。
最少花费: 2 + 5 + 3 = 10。

/**
 * @param {number[][]} costs
 * @return {number}
 */
var minCost = function (costs) {
    let len = costs.length
    if (len <= 0) return costs
    let dp = Array.from(new Array(len).fill(0), () => new Array(3).fill(0))
    dp[0] = costs[0]
    for (let i = 1; i < len; i++) {
        dp[i][0] = costs[i][0] + Math.min(dp[i - 1][1], dp[i - 1][2])
        dp[i][1] = costs[i][1] + Math.min(dp[i - 1][0], dp[i - 1][2])
        dp[i][2] = costs[i][2] + Math.min(dp[i - 1][0], dp[i - 1][1])
    }
    // return Math.min.call(null, dp[len - 1])
    return Math.min(...dp[len - 1])
};

比特位计数_中等

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。

示例 1:

输入: 2 输出: [0,1,1] 示例 2:

输入: 5 输出: [0,1,1,2,1,2]

var countBits = function (num) {
    let dp = []
    dp[0] = 0
    for (let i = 1; i <= num; i++) {
        if(i%2 === 0){
            dp[i] = dp[i/2]
        }else{
            dp[i] = dp[i-1] + 1 
        }
    }
    return dp
};

单词拆分_中等

给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
说明:拆分时可以重复使用字典中的单词。 你可以假设字典中没有重复的单词。
示例 1: 输入: s = “leetcode”, wordDict =[“leet”, “code”] 输出: true 解释: 返回 true 因为 “leetcode” 可以被拆分成 “leet code”。
示例 2: 输入: s = “applepenapple”, wordDict = [“apple”, “pen”] 输出:true 解释: 返回 true 因为 “applepenapple” 可以被拆分成 “apple pen apple”。
注意你可以重复使用字典中的单词。 示例 3: 输入: s = “catsandog”, wordDict = [“cats”, “dog”, “sand”, “and”, “cat”] 输出: false

/**
 * @param {string} s
 * @param {string[]} wordDict
 * @return {boolean}
 */
var wordBreak = function (s, wordDict) {
    let len = s.length
    let arr = new Array(len + 1).fill(false)
    arr[0] = true
    for (let i = 1; i <= len; i++) {
        for (let j = 0;j < i; j++) {
            if(arr[j] && wordDict.includes(s.slice(j,i))){
                arr[i]=true
            }
        }
    }
    return arr[len]
};

编辑距离_困难

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符 删除一个字符 替换一个字符 示例 1:

输入: word1 = “horse”, word2 = “ros” 输出: 3 解释: horse -> rorse (将 ‘h’
替换为 ‘r’) rorse -> rose (删除 ‘r’) rose -> ros (删除 ‘e’) 示例 2:

输入: word1 = “intention”, word2 = “execution” 输出: 5 解释: intention ->
inention (删除 ‘t’) inention -> enention (将 ‘i’ 替换为 ‘e’) enention ->
exention (将 ‘n’ 替换为 ‘x’) exention -> exection (将 ‘n’ 替换为 ‘c’) exection
-> execution (插入 ‘u’)
编辑距离

var minDistance = function (word1, word2) {
    let str1 = ' ' + word1;
    let str2 = ' ' + word2;
    const n = str1.length, m = str2.length;
    if (n * m === 0) {
        return n + m;
    }
    let dp = [...new Array(n)].map(() => new Array(m));
    for (let i = 0; i < n; i++) {
        dp[i][0] = i;
    }
    for (let j = 0; j < m; j++) {
        dp[0][j] = j;
    }
    for (let i = 1; i < n; i++) {
        for (let j = 1; j < m; j++) {
            if (str1[i] === str2[j]) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = Math.min(dp[i][j - 1], dp[i - 1][j], dp[i - 1][j - 1]) + 1
            }
        }
    }
    return dp[n - 1][m - 1]
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值