20天速通LeetCodeday17:一维动态规划

前言

今日练习目的:从一维动态规划入手,理解"子问题是更小规模的父问题与子问题最优解"两大核心特征,建立"用历史结果推导当前解"的思维。

重要思维突破:理解动态规划本质是用数组记录子问题答案,吧自顶向下的递归,转化为自底向上的递推,但要注意,并非所有递归都可以转为动态规划。

509:斐波那契数列

题目要求:给定一个整数n,求第n个斐波那契数

核心思路(一维动态规划)

用数组dpi存储第i个斐波那契数

遍历从2到n

dpi=dpi-1+dpi-2

代码实现

java 复制代码
class Solution {
    public int fib(int n) {
        if(n==0) return 0;
        if(n==1) return 1;

        int[] dp=new int[n+1];//dp[i]表示第i个斐波那契数
        dp[0]=0;
        dp[1]=1;

        for(int i=2;i<=n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];

    }
}

总结

作为入门的一维动态规划。核心需要理解:一维DP就是沿着线性状态从前往后累积计算,每个状态只依赖前两个状态

53:最大子数组和

题目要求:给定一个整数数组nums,找出一个拦蓄子数组,使得他们的和最大

要求:返回这个最大和

核心思路

假设dpi表示以numsi结尾的最大子数组和:dpi = max(dpi-1 + numsi, numsi)

如果把前面的子数组加上numsi比numsi小-就从numsi重新开始

每一步更新全局最大值maxSum

代码实现

java 复制代码
int n=nums.length;
int[] dp=new int[n]
dp[0]=nums[0];
int maxSum=dp[0];

for(int i=1;i<n;i++){
dp[i]=Math.max(dp[i-1]+nums[i];nums[i]);//状态转移
maxSum=Math.max(maxSum,dp[i]);
}
return maxSum;

总结

本题重点只有一个,就是理解dpi的递增实现

理解dpi = max(dpi-1 + numsi, numsi)就能掌握本题

想要讲的重点是关于递归和一维动态规划的区别

递归的特点是:

自己调用自己,没有记录已经计算过的结果

DP的特点是:

讲递归的重复计算结果记住

用一个数组dpi存储每个状态的结果

自底向上(从小状态开始计算到大状态)

198:打家劫舍

题目要求:

有一个整数数组nums,表示每个房子里的钱,你不能抢相邻的房子,求你能抢到的最大金额。

核心思路

对于每个房子i,有两个选择:

  1. 抢当前房子-就不能抢上一个房子,只能加上dpi-2;
  2. 不抢当前房子-最大金额=dpi-1
    状态转移方程:dpi = max(dpi-1, dpi-2 + numsi)

代码实现

java 复制代码
if(nums.length==0||nums==null) return 0;
if(nums.length==1) return nums[0];

int n=nums.length;
int[] dp=new int[n];
dp[0]=nums[0];
dp[1]=nums[1];

for(int i=2;i<n;i++){
dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[i-1];

总结

理解一维动态规划的本质是:用数组记录子问题的答案。通过记录下来 的答案来获得父问题。

也就是说难点在于找出特征方程。

对于本题来说:每一遍历到一个房子i,都面临两个选项;1.抢(代表前一个房子不能抢)2.不抢(抢前一个房子)

dpi=max(dpi-2+numsi,dpi-1)

300:最长递增子序列

题目要求:

给定一个整数数组nums,找到其中最长严格递增子序列长度

核心思路

先定义dpi=以numsi结尾的最长递增子序列长度

状态转移方程:dpi=max(dpj+1) for all j < i and numsj < numsi

对于每个numsi,找前面所有比它小的numsj

初始化dpi=1

代码实现

java 复制代码
if(nums.length==0||nums==null) return 0;
int n=nums.length;
int[] dp=new int[n];
int maxLen=1;
Arrays.fill(dp,1)

for(int i=1;i<n;i++){
for(int j=1;j<n;j++){
if(nums[i]>nums[j]{
dp[i]=Math.max(dp[i],dp[j+1]);
}
}
mxaLen=Math.max(maxLen,dp[i]);
}

总结

本题最具有难度的是想到通过i和j两个变量,一个前一个后来判断递增数组是否增加,命dpi为以numsi为结尾的最长递增子序列长度

状态转移方程:dpi = max(dpj + 1) for all j < i and numsj < numsi

139:单词拆分

题目要求:给定一个字符串s和一个单词字典wordDict

要求:判断是否可以用字典里的单词完全拼接成s。

核心思路

动态规划定义状态:dpi=true/false表示s0...i-1是否可以被字典拆分

状态转移方程:dpi=dpj&&wordDict.contains(sj...i-1)

代码实现

java 复制代码
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        Set<String> wordSet=new HashSet<>(wordDict);//查找O(1)
        int n=s.length();
        boolean[] dp=new boolean[n+1];
        dp[0]=true;//空字符串可拆分
        
        for(int i=1;i<=n;i++){//子串长度
            for(int j=0;j<i;j++){
                if(dp[j]&&wordSet.contains(s.substring(j,i))){
                    dp[i]=true;
                    break;//找到一个拆分即可
                }
            }
        }
        return dp[n];
    }
}
相关推荐
爱刷碗的苏泓舒3 小时前
PPP-AR 中的参考星选取:数学原理、评价指标与切换处理
算法·gnss·模糊度固定·ppp-ar·星间单差·参考星·卫星端偏差
烬羽6 小时前
递归老写崩?一个"退回"公式,把回溯题变成填空题
javascript·深度学习·算法
闪电悠米6 小时前
力扣hot100-41.缺失的第一个正数-原地哈希详解
数据结构·算法·哈希算法
星空露珠6 小时前
28种颜色对应名称,
开发语言·数据库·算法·游戏·lua
QXWZ_IA8 小时前
桥梁数字孪生怎么落地?
人工智能·科技·算法·智能硬件·政务
Kel8 小时前
输出层与反分词(Output Layer & Detokenization)
人工智能·算法·架构
陕西企来客8 小时前
2026年7月技术好GEO优化方案:算法适配与内容策略
人工智能·算法·机器学习·技术好geo优化
风栖柳白杨9 小时前
【面试】AI算法工程师_空白自测版本
人工智能·算法·面试
闪电悠米10 小时前
力扣hot100-73.矩阵置零-标记数组详解
算法·leetcode·矩阵
栋***t10 小时前
从“纸质试卷”到“AI智能组卷”,麦塔在线考试系统如何重构出题逻辑?
java·大数据·人工智能·算法·重构