【LeetCode题解】动态规划(一)

文章目录

  • 斐波那契数
  • 爬楼梯
  • 使用最小花费爬楼梯
  • 最大子数组和
  • 打家劫舍




斐波那契数

思路分析

  • 设计状态量:题目提供 n≤30 ,所以只需要开数组 32 就够用了;
  • 初始化状态: f[0] = 0,f[1] = 1 这一步可以在定义数组时声明;
  • 状态转移方程: f[i]=f[i-1]+f[i-2]

代码示例

int fib(int n){
    int f[32] = {0,1};
    for(int i=2;i<n+1;++i)
            f[i]=f[i-1]+f[i-2];
    return f[n];
}

爬楼梯

思路分析

  • 题意分析,上到台阶 i 有两种方式,从 i-1 或者 i-2 的台阶上去,原型是 斐波那契数,而需要注意,本题中 f[0] = 1 ,其余与上一题相同;

代码示例

int climbStairs(int n){
    int f[50] = {1,1};
    for(int i = 2;i<=n;++i)
        f[i] = f[i-1] + f[i-2];
    return f[n];
}

使用最小花费爬楼梯


思路分析

  • 题意分析:本题题意同第二题相似,不一样的是每一次爬楼梯都需要一定的花费
  • 确定状态转移方程:
dp[i] 表示 到第 i 台阶所需要的花费,到达 i 层台阶 所需要的费用有两种可能
1、从 i-1 层到 i 层  ,费用为 dp[i-1] + cost[i] 
2、从 i-2 层到 i 层  ,费用为 dp[i-2] + cost[i]
而本题是求最小,所以只需要取 1 、2两种方式的最小费用即可。
即,dp[i] = min(dp[i-1] + cost[i] ,dp[i-2] + cost[i] );
  • 初始化状态:题目要求,可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。所以dp[0] = 0,dp[1] = 0 ;

代码示例

int min(int a,int b)
{
    return a<b?a:b;
}
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int dp[1001] = {0,0};
        for(int i =2; i<= cost.size() ;++i)
        {
            dp[i] = min(dp[i-1] + cost[i-1],dp[i-2] + cost[i-2]);
        }
        return dp[cost.size()];
    }   

最大子数组和

思路分析

  • 题意理解 要我们找出和最大的连续子数组的值是多少,并返回其最大值
  • 确定初始状态
    定义动态数组 dp[100010],以及最终返回值 numberValue,并赋初始值 dp[0] = nums[0] , numberValue = nums[0] ;
  • 确定状态转移方程:转化过程考虑的是 dp[i-1]是否大于零,如果dp[i-1]>0,则其加上 以nums[i-1]结尾的子数组 即,dp[i-1] 之和最大,也就是 dp[i] 获得正向增长的,此时,dp[i] = dp[i-1] + nums[i];反之,dp[i-1]小于零,那加上他还没我自己另起炉灶大,所以另起炉灶,dp[i] = nums[i]。
if(dp[i-1]0) 
	dp[i] = dp[i-1] + nums[i]else 
	dp[i] =nums[i];

可以简化成

dp[i]max(dp[i-1] + nums[i],nums[i]);

代码示例

class Solution {
public:
    int max(int a,int b)
    {
        return a>b?a:b;
    }
    int maxSubArray(vector& nums) {
        int dp[100010];    
        int numberValue = nums[0];
        dp[0] = nums[0];
        for(int i = 1 ;i

打家劫舍


思路分析

  • 题意分析,相当于给定一个整数 n, 再给定 n 个整数的数组 nums ,相邻两个数组不能重复取,求选出来的整数之和最大。
  • 确定状态,定义数组 dp[i] ,表示 前 i 个整数 通过某种选取方案能够获得的最大值。
  • 确定状态转移方程,如果 i 可以取,那么 i-1 不可取,而 i-2 可取可不取,所以转换成 dp[i-2] 的子问题,所以方程为       dp[i] = max(dp[i-1],dp[i-2] + nums[i]) ;
  • 确定初始值,以第 0 个元素结尾的最大值 ,dp[0] = nums[0] ;

int max(int a,int b)
{
    return a>b?a:b;
}
int rob(int* nums, int numsSize){
    int dp[101];  //定义一个状态数组 
    dp[0] = nums[0];
    for(int i = 1;i< numsSize;++i)
    {
        if(i == 1)    //防止 i-2 时 数组下标越界
            dp[1] = max(nums[0],nums[1]);
        else
            dp[i] = max(dp[i-1],dp[i-2] + nums[i]); 
    }
    return dp[numsSize-1];
}

分析
题型,线性dp;
时间复杂度,O(1);

你可能感兴趣的:(#,LeetCode,题解,leetcode,动态规划,算法)