【力扣】从零开始的动态规划

【力扣】从零开始的动态规划

文章目录

  • 【力扣】从零开始的动态规划
    • 开头
    • 139. 单词拆分
      • 解题思路
    • 45. 跳跃游戏 II
      • 解题思路
    • 5. 最长回文子串
      • 解题思路
    • 1143. 最长公共子序列
      • 解题思路
    • 931. 下降路径最小和
      • 解题思路

开头

本力扣题解用5题来引出动态规划的解题步骤,用于本人进阶掌握动态规划,在刷题过程中写下的一些解题步骤与思路,供大家一起学习

139. 单词拆分

139. 单词拆分

给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s

**注意:**不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。

解题思路

状态表示: dp[i]表示字符串以0到i-1的字符串,能否组成字串

初始状态:dp[0]=true,没有字符串的情况肯定为true,如果这个为false,那么后面全部为false

状态转移方程:

​ 可以把一个字符串来看成两段,0~j-1j~i,前面一半可以看成dp[j],因为看下状态表示就知道了,dp[i]表示字符串以0到i-1的字符串, 带入j得dp[j]表示字符串以0到j-1的字符串。

​ 后一半直接在哈希表中找子串是否存在,找到了就是true,如果两个字串同时为true,那么dp[i]=true

​ 因为以0~i的字符串的分解的情况有很多种,只要其中一种为true,那么就是true,直接break

​ 所以动态转移方程为:

            if(dp[j] && set.contains(s.substring(j,i))){dp[i]=true;break;}
import java.util.HashSet;
import java.util.Set;class Solution {public boolean wordBreak(String s, List<String> wordDict) {Set<String> set=new HashSet<>(wordDict);int n=s.length();boolean[] dp=new boolean[n+1];dp[0]=true;//从第i个字符结束的for(int i=0;i<=n;i++){for(int j=0;j<i;j++){if(dp[j] && set.contains(s.substring(j,i))){dp[i]=true;break;}}}return dp[n];}
}

45. 跳跃游戏 II

45. 跳跃游戏 II

给定一个长度为 n0 索引整数数组 nums。初始位置为 nums[0]

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

  • 0 <= j <= nums[i]
  • i + j < n

返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]

解题思路

状态表示: dp[i]表示从1开始跳到第i个数的最小次数

​ **初始状态:**第1个元素是起点,可以到达,其他所有结点默认无法到达,设置一个很大的初始值

状态转移方程:

​ 第i个数可以从前面任意一个跳跃距离大于两个结点距离的结点,及判断条件if(nums[j]>=i-j),在这些满足要求的结点中取最小值,方程为

dp[i]=min(dp[0],dp[1],dp[2]...dp[n-1])+1,写成循环结构,最终方程为:dp[i]=Math.min(dp[i],dp[j]+1);

import java.util.Arrays;class Solution {public int jump(int[] nums) {int n=nums.length;int[] dp=new int[n];Arrays.fill(dp,Integer.MAX_VALUE);//状态表示:前跳到第i个的最小次数dp[0]=0;for(int i=1;i<n;i++){for(int j=0;j<i;j++){int l=i-j;if(nums[j]>=l){dp[i]=Math.min(dp[i],dp[j]+1);}}}return dp[n-1];}
}

5. 最长回文子串

5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

解题思路

状态表示: dp[i][j] 表示 i到j是否是一个回文串

​ **初始状态:**无

状态转移方程:

​ 想要知道dp[i][j]是否是一个回文子串,只需知道dp[i+1][j-1]是否是一个回文子串并且外层的字符相等即s[i]==s[j],那么dp[i][j]就是一个回文子串,还有一种特殊情况是:要判断的字符串只有两个字符时,不用再判断dp[i+1][j-1]是否是一个回文子串,只需判断这两个字符是否相等即可

​ **循环顺序:**想要知道循环顺序是从大到小,还是从小到大,我们要知道dp数组中哪个要先算出来 ,哪个后算出来,比如想要知道dp[i][j]是否是一个回文子串,就得先知道dp[i+1][j-1]是否也是一个回文子串,所以dp[i+1][j-1]要被先计算出来,分为两重循环来分析

​ 外重循环i+1比i要先知道,所以,i从大到小循环

​ 内重循环j-1比j要先知道,所以j从小到大循环

​ 又因为j一定要大于等于i,因为范围表示是i~j,所以j从i到n-1

            if(s.charAt(i)==s.charAt(j)){if(j-i<2 || dp[i+1][j-1] )dp[i][j]=true;}
class Solution {public String longestPalindrome(String s) {int n=s.length();//状态表示:i到j是否是一个回文串boolean[][] dp=new boolean[n][n];//dp[i][j]=dp[i+1][j-1] && s.charAt(i)==s.charAt(j)String str="";for(int i=n-1;i>=0;i--){for(int j=i;j<n;j++){if(s.charAt(i)==s.charAt(j)){if(j-i<2 || dp[i+1][j-1] )dp[i][j]=true;}if(dp[i][j] && (j-i+1)>str.length()){str=s.substring(i,j+1);}}}return str;}
}

1143. 最长公共子序列

1143. 最长公共子序列

给定两个字符串 text1text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

  • 例如,"ace""abcde" 的子序列,但 "aec" 不是 "abcde" 的子序列。

两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

解题思路

状态表示:dp[i][j] 表示 text1[0:i-1]text2[0:j-1] 的最长公共子序列

**状态转移方程:**知道状态定义之后,我们开始写状态转移方程。

​ 当 text1[i - 1] == text2[j - 1] 时,说明两个子字符串的最后一位相等,所以最长公共子序列又增加了 1,所以 dp[i][j] = dp[i - 1][j - 1] + 1;举个例子,比如对于 ac 和 bc 而言,他们的最长公共子序列的长度等于 a 和 b 的最长公共子序列长度 0 + 1 = 1。
text1[i - 1] != text2[j - 1] 时,说明两个子字符串的最后一位不相等,那么此时的状态 dp[i][j] 应该是 dp[i - 1][j]dp[i][j - 1] 的最大值。举个例子,比如对于 ac和 bc 而言,他们的最长公共子序列的长度等于 ① ace 和 b 的最长公共子序列长度0 与 ② ac 和 bc 的最长公共子序列长度1 的最大值,即 1。

​ 所以状态转移方程为:当text[i-1]==text[j-1]时.dp[i][j]=dp[i-1][j-1]+1

​ 当text[i-1]!=text[j-1]时,dp[i][j]=max(dp[i−1][j],dp[i][j−1])

**初始值:**初始化就是要看当 i = 0 与 j = 0 时, dp[i][j] 应该取值为多少。

当 i = 0 时,dp[0][j] 表示的是 text1 中取空字符串 跟 text2 的最长公共子序列,结果肯定为 0.
当 j = 0 时,dp[i][0] 表示的是 text2 中取空字符串 跟 text1 的最长公共子序列,结果肯定为 0.
综上,当 i = 0 或者 j = 0 时,dp[i][j] 初始化为 0.

遍历方向与范围:由于 dp[i][j] 依赖与 dp[i - 1][j - 1] , dp[i - 1][j], dp[i][j - 1],所以 iii 和 jjj 的遍历顺序肯定是从小到大的。 另外,由于当 i 和 j 取值为 0 的时候,dp[i][j] = 0,而 dp 数组本身初始化就是为 0,所以,直接让 i 和 j 从 1 开始遍历。遍历的结束应该是字符串的长度为 len(text1) 和 len(text2)

class Solution {public int longestCommonSubsequence(String text1, String text2) {int n=text1.length();int m=text2.length();int[][] dp=new int[n+1][m+1];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(text1.charAt(i-1)==text2.charAt(j-1))dp[i][j]=dp[i-1][j-1]+1;elsedp[i][j]=Math.max(dp[i-1][j],dp[i][j-1]);}}return dp[n][m];}
}

931. 下降路径最小和

931. 下降路径最小和

给你一个 n x n方形 整数数组 matrix ,请你找出并返回通过 matrix下降路径最小和

下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)(row + 1, col) 或者 (row + 1, col + 1)

示例 1:

img

输入:matrix = [[2,1,3],[6,5,4],[7,8,9]]
输出:13
解释:如图所示,为和最小的两条下降路径

解题思路

状态表示:dp[i][j]表示走到matrix[i][j]的最小下降和

**初始值:**第一行全是0,因为在原地(起点)

**状态转移方程:**到达dp[i][j]可以从上一层的相邻元素到达,取其中的最小值并加上一步的数量,即dp[i][j]=min(dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1])+matrix[i][j],因为要判断边界条件,在最左边和最右边只能从上一层的两个到达。

​ 综上所诉,状态转移方程为:

if(j==0)dp[i][j]=Math.min(dp[i-1][j],dp[i-1][j+1])+matrix[i][j];
else if(j==m-1)dp[i][j]=Math.min(dp[i-1][j-1],dp[i-1][j])+matrix[i][j];
elsedp[i][j]=Math.min(dp[i-1][j-1],Math.min(dp[i-1][j],dp[i-1][j+1]))+matrix[i][j];

**答案:**根据题目要求,到达最后一行的最少下降和,再看状态表示:dp[i][j]表示走到matrix[i][j]的最小下降和,所以答案就在dp的最后一行中,取最后一行的最小值即是答案

class Solution {public int minFallingPathSum(int[][] matrix) {int n=matrix.length;int m=matrix[0].length;int[][] dp=new int[n][m];for(int j=0;j<m;j++){dp[0][j]=matrix[0][j];}for(int i=1;i<n;i++){for(int j=0;j<m;j++){if(j==0)dp[i][j]=Math.min(dp[i-1][j],dp[i-1][j+1])+matrix[i][j];else if(j==m-1)dp[i][j]=Math.min(dp[i-1][j-1],dp[i-1][j])+matrix[i][j];elsedp[i][j]=Math.min(dp[i-1][j-1],Math.min(dp[i-1][j],dp[i-1][j+1]))+matrix[i][j];}}int min=Integer.MAX_VALUE;for(int j=0;j<m;j++){min=Math.min(min,dp[n-1][j]);}return min;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/148308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android图片涂鸦,Kotlin(1)

Android图片涂鸦&#xff0c;Kotlin&#xff08;1&#xff09; import android.content.Context import android.graphics.Canvas import android.graphics.Color import android.graphics.Paint import android.graphics.Path import android.graphics.PointF import android.…

UE4动作游戏实例RPG Action解析三:实现效果,三连击Combo,射线检测,显示血条,火球术

一、三连Combo 实现武器三连击,要求: 1.下一段Combo可以随机选择, 2.在一定的时机才能再次检测输入 3. 等当前片段播放完才播放下一片段 1.1、蒙太奇设置 通过右键-新建蒙太奇片段,在蒙太奇里创建三个片段,并且移除相关连接,这样默认只会播放第一个片段 不同片段播…

图像分类(六) 全面解读复现MobileNetV1-V3

MobileNetV1 前言 MobileNetV1网络是谷歌团队在2017年提出的&#xff0c;专注于移动端和嵌入设备的轻量级CNN网络&#xff0c;相比于传统的神经网络&#xff0c;在准确率小幅度降低的前提下大大减少模型的参数与运算量。相比于VGG16准确率减少0.9%&#xff0c;但模型的参数只…

基于Vue+SpringBoot的大病保险管理系统 开源项目

项目编号&#xff1a; S 031 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S031&#xff0c;文末获取源码。} 项目编号&#xff1a;S031&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大…

SDUT OJ《算法分析与设计》搜索算法

A - 子集和问题 Description 子集和问题的一个实例为〈S,t〉。其中&#xff0c;S{ x1 &#xff0c; x2 &#xff0c;…&#xff0c;xn }是一个正整数的集合&#xff0c;c是一个正整数。子集和问题判定是否存在S的一个子集S1&#xff0c;使得&#xff1a; 。 试设计一个解子…

坐标系下的运动旋量转换

坐标系下的运动旋量转换 文章目录 坐标系下的运动旋量转换前言一、运动旋量物体运动旋量空间运动旋量 二、伴随变换矩阵三、坐标系下运动旋量的转换四、力旋量五、总结参考资料 前言 对于刚体而言&#xff0c;其角速度可以写为 ω ^ θ ˙ \hat {\omega} \dot \theta ω^θ˙&…

Pytorch torch.exp()的使用举例

代码实验展示: Microsoft Windows [版本 10.0.18363.1256] (c) 2019 Microsoft Corporation。保留所有权利。C:\Users\chenxuqi>conda activate ssd4pytorch1_2_0(ssd4pytorch1_2_0) C:\Users\chenxuqi>python Python 3.7.7 (default, May 6 2020, 11:45:54) [MSC v.191…

STL总结

STL vector 头文件<vector> 初始化,定义,定义长度&#xff0c;定义长度并且赋值&#xff0c;从数组中获取数据返回元素个数size()判断是否为空empty()返回第一个元素front()返回最后一个数back()删除最后一个数pop_back()插入push_back(x)清空clear()begin()end()使用s…

SQL SERVER 2008安装教程

SQL SERVER 2008安装教程 本篇文章介绍了安装SQL Server 2008企业版的软硬件配置要求&#xff0c;安装过程的详细步骤&#xff0c;以及需要注意的事项。 安装步骤 (1). 在安装文件setup.exe上&#xff0c;单击鼠标右键选择“以管理员的身份运行”&#xff0c;如下图所示&#…

皮肤性病科专家谭巍主任提出HPV转阴后饮食七点建议

HPV转阴是每一位感染者都期盼的&#xff0c;因为转阴所以健康&#xff0c;只有转为阴性才意味着不具备传染性&#xff0c;从此也不必再害怕将病毒传染给家人的风险&#xff0c;也不必再担忧持续感染而引发的健康风险。总之&#xff0c;HPV转阴是预示感染者恢复健康与否的主要标…

《洛谷深入浅出进阶篇》P1995 程序自动分析——并查集,离散化

上链接&#xff1a;P1955 [NOI2015] 程序自动分析 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1955 上题干&#xff1a; 首先给你一个整数t&#xff0c;代表t次操作。 每一次操作包含以下内容&#xff1a; 1.给你一个整数n&#xff0c;让…

【机器学习13】生成对抗网络

1 GANs的基本思想和训练过程 生成器用于合成“假”样本&#xff0c; 判别器用于判断输入的样本是真实的还是合成的。 生成器从先验分布中采得随机信号&#xff0c;经过神经网络的变换&#xff0c; 得到模拟样本&#xff1b; 判别器既接收来自生成器的模拟样本&#xff0c; 也接…

数据结构:红黑树讲解(C++)

红黑树 1.前言2.红黑树简述2.1概念2.2性质 3.红黑树的插入3.1关于新插入节点的颜色3.2节点的定义3.3插入新节点3.4判断插入后是否需要调整3.5插入后维持红黑树结构&#xff08;重点&#xff09;3.5.1cur、p、u为红&#xff0c;g为黑3.5.2cur、p为红&#xff0c;g为黑&#xff0…

【【VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 】】

VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 VDMA彩条显示实验之三 之 RGB LCD 彩条显示实验 LCD 的构造是在两片平行的玻璃基板当中放置液晶盒&#xff0c;下基板玻璃上设置 TFT&#xff08;薄膜晶体管&#xff09;&#xff0c;上基板玻璃上设置彩色滤光片&#xff0c;通…

Flutter 应用启动从闪屏页短暂黑屏再到第一个页面

由于应用初始状态启动会有白屏现象&#xff0c;便使用 flutter_native_splash 2.3.5 插件生成了启动相关的配置&#xff0c;并且按照示例使用了 import package:flutter_native_splash/flutter_native_splash.dart;void main() {WidgetsBinding widgetsBinding WidgetsFlutte…

牛客 —— 链表中倒数第k个结点(C语言,快慢指针,配图)

目录 1. 思路1&#xff1a;倒数第K个节点&#xff0c;就是整数第N-K1的节点 2. 思路2&#xff1a;快慢指针 1. 思路1&#xff1a;倒数第K个节点&#xff0c;就是整数第N-K1的节点 链表中&#xff0c;一共有N个节点&#xff0c;如果我们想要得出倒数第K个节点&#xff0c;我们…

图像倾斜角度求取-Radon变换

Radon算法 Radon&#xff08;拉东&#xff09;算法是一种通过定方向投影叠加&#xff0c;找到最大投影值时角度&#xff0c;从而确定图像倾斜角度的算法。具体过程如图所示 图1 Radon变换算法 Radon计算示例 对于纹理方向明显的图像&#xff0c;如图2所示&#xff0c;可以通…

【设计模式】聊聊模板模式

原理和实现 设计模式的原理和实现是比较简单的&#xff0c;难的是掌握具体的应用场景和解决什么问题。而模板模式是为来解决复用和拓展两个问题。 模板模式在一个方法中定义好一个算法框架&#xff0c;然后将某些步骤推迟到子类中实现&#xff0c;子类可以在不修改父类流程的时…

qsort使用举例和qsort函数的模拟实现

qsort使用举例 qsort是C语言中的一个标准库函数&#xff0c;用于对数组或者其他数据结构中的元素进行排序。它的原型如下&#xff1a; void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 我们可以去官网搜来看一看&#xff1a;…

lxml基本使用

lxml是python的一个解析库&#xff0c;支持HTML和XML的解析&#xff0c;支持XPath解析方式&#xff0c;而且解析效率非常高 XPath&#xff0c;全称XML Path Language&#xff0c;即XML路径语言&#xff0c;它是一门在XML文档中查找信息的语言&#xff0c;它最初是用来搜寻XML文…