当前位置: 首页 > news >正文

【动态规划】子数组系列(下)

在这里插入图片描述

1. 等差数列划分

413. 等差数列划分

状态表示:以 i 位置为结尾时的等差数列的个数

状态转移方程:由于至少需要三个元素才符合题目中等差数列的要求,所以需要判断 i - 2,i - 1,i 三个元素,当这三个元素符合等差数列时,那么以 i - 1 为结尾的等差数列再加上 i 也是等差数列,等差数列的个数就 + 1,如果说这三个元素不符合等差数列,那么以 i 为结尾的等差数列个数就是 0

初始化:由于三个元素才能进行等差数列的判断,所以 dp[0],dp[1] 初始化为 0

返回值:如果数组长度小于 3 直接返回 0,大于等于 3 就返回 dp 数组的和

class Solution {public int numberOfArithmeticSlices(int[] nums) {int n = nums.length;int[] dp = new int[n];int ret = 0;if(n < 3) return 0;for(int i = 2;i < n;i++){dp[i] = (nums[i] - nums[i - 1]) == (nums[i - 1] - nums[i - 2]) ? dp[i - 1] + 1:0; ret += dp[i];}return ret;}
}

2. 最长湍流子数组

978. 最长湍流子数组

状态表示:先用 dp[i] 来表示以第 i 个位置为结尾时的最长湍流数组的长度

f[i]:表示以第 i 个位置为结尾时表示上升状态的最长湍流数组的长度

f[i]:表示以第 i 个位置为结尾时表示下降状态的最长湍流数组的长度

状态转移方程:

第 i - 1 和 i 位置的状态可能会有下降,上升,相等三种状态,所以定义一个 dp 状态就不够了,需要定义一个上升状态和一个下降状态,当 i - 1 到 i 处于下降状态时,之前应该是处于上升状态的,也就是 f[i - 1],再加上 1 就是以第 i 个位置为结尾时处于下降状态的最长数组长度,上升也是一样的道理,需要在第 i - 1 位置处于下降状态,就是 g[i - 1] + 1,相等时等于 1 即可

初始化:由于 1 个元素也可以称为湍急子数组,所以可以把 0 下标初始化为 1,又因为状态转移方程中的其他情况是 1 ,为了方便,可以把初始的两个 dp 表都初始化为 1

填表顺序:从左到右

返回值:下降和上升状态的最大值

class Solution {public int maxTurbulenceSize(int[] arr) {int n = arr.length;int[] f = new int[n];int[] g = new int[n];for(int i = 0;i < n;i++){f[i] = g[i] = 1;}int ret = 1;for(int i = 1;i < n;i++){if(arr[i] > arr[i - 1]){g[i] = f[i - 1] + 1;}else if(arr[i] < arr[i - 1]){f[i] = g[i - 1] + 1;}ret = Math.max(Math.max(ret,g[i]),f[i]);}return ret;}
}

3. 单词拆分

139. 单词拆分

状态表示:dp[i] 表示以 i 为结尾时,区间 [0 , i] 之间内能否被字典中的单词拼接而成

状态转移方程:

可以把区间分为两段,设 j 为最后一个单词的起始位置的下标,如果 [0 , j - 1] 区间内能够被字典中的单词拼接而成,也就是 dp[j - 1],再加上 j ~ i 区间的单词在数组中,那么就说明 0 ~ i 区间可以被字典中的单词拼接而成

初始化:为了方便表示 ,dp 数组还是开 n + 1(n 为所给字符串的长度),此时 dp[0] 需要设置为 true 才能不影响后续的判断,如果是 false 的话,那么后面区间就一直都不可以被拼接,dp 数组长度 + 1 之后,为了更方便的表示下标的映射关系,可以把原来的字符串 s 最前面加一个长度为 1 的占位符,这样字符串的下标也对应着 dp 表的下标

填表顺序:从左到右

返回值:dp[n]

为了便于查找 j ~ i 的字符串是否在字典中,可以把题中的字典映射到哈希表中

class Solution {public boolean wordBreak(String s, List<String> wordDict) {int n = s.length();boolean[] dp = new boolean[n + 1];dp[0] = true;s = " " + s;Set<String> hash = new HashSet(wordDict);for(int i = 1;i <= n;i++){//字符串长度 + 1,对应的 j 最小就是 1 下标for(int j = i;j >= 1;j--){//substring 前闭后开 ,所以 i + 1if(dp[j - 1] && hash.contains(s.substring(j,i + 1))){dp[i] = true;//如果找到一种再往前就不用找了break;}}   }return dp[n];}
}

4. 环绕字符串中唯一的子字符串

467. 环绕字符串中唯一的子字符串

状态表示:dp[i] 表示以 i 位置为结尾时,有多少子串出现

状态转移方程:

和上一题其实差不多,可以分为长度为 1 和长度大于 1 的,只需要判断是否是连续的,前一个是“z”后一个是 "a" 也算是连续的

初始化:由于长度为 1 时可以算出现一次,长度大于 1 就是找到以 i - 1 为结尾的子串再加上 s[i] ,整体的数量还是 dp[i - 1],dp[i] 就是把长度为 1 和长度大于 1 的两种情况加起来,所以可以把整个 dp 表初始化为 1 ,然后就只需要判断长度大于 1 时的情况直接相加就行

填表顺序:从左到右

返回值:由于 dp[i] 中存储的是以 i 为结尾时的子串出现的次数,这就可能出现多次,例如“cac”

相同的子串只能统计一次,并且可以发现,以同一个字符结尾的子串只需要统计最长的即可,短的情况就包含在了长的情况,所以可以额外定义一个 hash 表来存储最终的答案,最后只需返回 hash 表中的所有和即可

class Solution {public int findSubstringInWraproundString(String s) {int n = s.length();int[] dp = new int[n];Arrays.fill(dp, 1);//表示 26 个字母int[] hash = new int[26];char[] chars = s.toCharArray();for(int i = 1;i < n;i++){if((chars[i] == (chars[i - 1] + 1)) || (chars[i] == 'a'&&chars[i - 1] == 'z')){dp[i] += dp[i - 1];}}int ret = 0;for(int i = 0;i < n;i++){//更新为以当前字符为结尾最长子串的数量hash[chars[i] - 'a'] = Math.max(hash[chars[i] - 'a'],dp[i]);}for(int x : hash) ret += x;return ret;}
}

在这里插入图片描述

http://www.lryc.cn/news/459935.html

相关文章:

  • macos mendeley Unable to install the Microsoft Word Plugin 解决
  • 【Linux进程间通信】Linux信号机制深度解析:保存与处理技巧
  • 常见开源组件的详解
  • rust使用教程详解
  • 并查集的实现(朴素版)
  • WPF 为button动态设置不同的模板
  • 【C++贪心 DFS】2673. 使二叉树所有路径值相等的最小代价|1917
  • 虚幻引擎GAS入门学习笔记(一)
  • Excel:vba实现合并工作表(表头相同)
  • Redis:分布式 - 主从复制
  • el-date-picker设置只有某些日期可选
  • java数据库操作-cnblog
  • HCIP-HarmonyOS Application Developer 习题(九)
  • redis集成到spring boot中使用
  • Spring Boot、Spring MVC和Spring有什么区别
  • Flip动画
  • Java通过RAG构建专属知识问答机器人_超详细
  • 2.1 使用点对点信道的数据链路层
  • 台式机来电自启动设置
  • 【最新华为OD机试E卷-支持在线评测】考勤信息(100分)多语言题解-(Python/C/JavaScript/Java/Cpp)
  • netdata保姆级面板介绍
  • 苹果最新论文:LLM只是复杂的模式匹配 而不是真正的逻辑推理
  • Python知识点:基于Python工具,如何使用Scikit-Image进行图像处理与分析
  • MongoDB初学者入门教学:与MySQL的对比理解
  • Oracle AI Vector Search
  • 基于SpringBoot的健身会员管理系统实战分享
  • Elasticsearch高级搜索技术-结构化数据搜索
  • ffmpeg面向对象——类所属的方法探索
  • TensorRT-LLM七日谈 Day3
  • 如何使用Pandas库处理大型数据集?