动态规划问题

一、动态规划

1、核心思想

将问题划分为若干个子问题,并在计算子问题的基础上,逐步构建出原问题的解

2、解题步骤

  1. 定义状态:将原问题划分为若干个子问题,定义状态表示子问题的解,通常使用一个数组或者矩阵来表示
  2. 确定状态转移方程:在计算子问题的基础上,逐步构建出原问题的解;这个过程通常使用“状态转移方程”来描述,表示从一个状态转移到另一个状态的转移规则
  3. 初始化状态
  4. 计算原问题的解(最终答案)
  5. 通过计算状态之间的转移,最终计算出原问题的解
  6. 通常使用递归或者迭代(循环)的方式计算

二、斐波那契数列

1、核心思想

从第二个数开始,每一个斐波那契数都是它前面两个斐波那契数之和

2、代码实现

1、递归的方法
function fib(n: number): number {
    // 0 1 1 2 3 5 8 13 21 34 55
    if(n <= 1) return n
    return fib(n - 1) + fib(n - 2)
}
console.log(fib(10))   // 55
2、记忆化搜索
function fib(n: number, memo: number[] = []): number {
    if(n <= 1) return n
    // 求n 的值,直接从memo 中取
    if(memo[n]) {
        return memo[n]
    }
    // 如果memo 中没有这个位置的值时,再去计算
    const res = fib(n - 1, memo) + fib(n - 1, memo)
    memo[n] = res
    return res
}
3、动态规划
function fib(n: number): number {
    // 1.定义状态
    // dp 保留斐波那契数列中每一个位置对应的值(状态)
    // dp[x]表示的就是x 位置对应的值
    // 2.状态转移方程:dp[i] = dp[i-1] + dp[i-2]
    // 状态转移方程一般情况都是写在循环中
    // 3.设置初始化状态:dp[0]/dp[1]初始化状态
    // 4.计算最终的结果

    // 1.定义状态
    // 2.初始化状态
    const dp: number[] = []
    dp[0] = 0
    dp[1] = 1
    // 3.状态转移方程
    for(let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2]
    }    
    //4.最终结果
    return dp[n]
}
4、状态压缩
function fib(n: number): number {
    if(n <= 1) return n
    // 1.定义状态
    // 2.初始化状态
    let prev = 0
    let cur = 1
    // 3.状态转移方程
    for(let i = 2; i <= n; i++) {
        const newValue = prev + cur
        prev = cur 
        cur = newValue
    }    
    //4.最终结果
    return cur
}

三、跳台阶(爬楼梯)

1、问题描述

一共有n 阶台阶,每次可以跳1 或 2阶台阶,问有多少种不同的跳法

2、核心思想

到达第n 阶台阶中能由第n - 1阶或第n - 2阶台阶跳上来

3、代码实现

1、动态规划
function jump(n: number): number {
    const dp: number[] = []  
    dp[0] = 1
    dp[1] = 1
    for(let i = 2; i <= n; i++) {
        dp[i] = dp[i - 1] + dp[i - 2]
    }
    return dp[n]
}    
2、状态压缩
function jump(n: number): number {
    let prev = 1
    let cur = 1
    for(let i = 2; i <= n; i++) {
        const newValue = prev + cur
        prev = cur
        cur = newVal
    }
    return cur
} 

四、买卖股票的最佳时机

1、问题描述

给定一组股票数据,选择在某一天买入这只股票,并选择在未来的某一个不同的日子卖出这只股票,计算能获取的最大利润

2、代码实现

1、动态规划
// maxProfit([7,1,5,3,6,0,4])  ->  5
function maxProfit(prices: number[]): number {
    const n = prices.length
    if(n <= 1) return 0
    const dp: number[] = []
    dp[0] = 0
    for(let i = 1; i < n; i++) {
        dp[i] = Math.max(prices[i] - minPrice, dp[i - 1])
        minPrice = Math.min(prices[i], minPrice)
    }
    return dp[n-1]
}
2、状态压缩
function maxProfit(prices: number[]): number {
    const n = prices.length
    if(n <= 1) return 0
    let preValue = 0
    let minPrice = prices[0]
    for(let i = 1; i < n; i++) {
        preValue = Math.max(prices[i] - minPrice, preValue)
        minPrice = Math.min(prices[i], minPrice)
    }
    return preValue
}    

五、最大子数组和

1、问题描述

在一个整数数组nums,找出一个具有最大和的连续子数组,(子数组最少包含一个元素),返回其最大和

例如:

输入:nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]

输出:6

解释:[4, -1, 2, 1]

2、代码实现

1、动态规划
function maxArray(nums: number[]): number {
    const n = nums.length
    const dp: number[] = []
    dp[0] = nums[0]
    for(let i = 1; i < n; i++) {
        dp[i] = Math.max(nums[i], nums[i] + dp[i - 1])
    }
    return Math.max(...dp)
}
2、状态压缩
function maxArray(nums: number[]): number {
    const n = nums.length
    let preValue = dp[0]
    let max = preValue
    for(let i = 1; i < n; i++) {
        preValue = Math.max(nums[i], nums[i] + preValue)
        max = Math.max(preValue, max)
    }
    return max
}

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值