文章目录

  • 系列文章目录
  • 前言
  • 题录
    • 647. 回文子串
    • 5. 最长回文子串
    • 516. 最长回文子序列
    • 132. 分割回文串 II

系列文章目录

一、 数组类型解题方法一:二分法
二、数组类型解题方法二:双指针法
三、数组类型解题方法三:滑动窗口
四、数组类型解题方法四:模拟
五、链表篇之链表的基础操作和经典题目
六、哈希表篇之经典题目
七、字符串篇之经典题目
八、字符串篇之 KMP
九、解题方法:双指针
十、栈与队列篇之经典题目
十 一、栈与队列篇之 top-K 问题
十 二、二叉树篇之二叉树的前中后序遍历
十 三、二叉树篇之二叉树的层序遍历及相关题目
十 四、二叉树篇之二叉树的属性相关题目
十 五、 二叉树篇之二叉树的修改与构造
十 六、 二叉树篇之二叉搜索树的属性
十 七、二叉树篇之公共祖先问题
十 八、二叉树篇之二叉搜索树的修改与构造
十 九、回溯算法篇之组合问题
二 十、回溯算法篇之分割、子集、全排列问题
二十一、贪心算法篇之入门题目
二十二、贪心算法篇之进阶题目
二十三、动态规划篇之基础题目
二十四、动态规划篇之背包问题:01背包
二十五、动态规划篇之背包问题:完全背包
二十六、动态规划篇之经典问题:打家劫舍
二十七、动态规划篇之买股票问题(一)
二十八、动态规划篇之子序列问题:连续子序列和不连续子序列
二十九、动态规划篇之子序列问题:编辑距离
更新中 …


前言


刷题路线来自 :代码随想录

题录

647. 回文子串

Leetcode 链接

题解:
方式一:动态规划
dp[i][j]: i 表示子串起始下标,j 表示子串结尾下标,该子串是否为字符串。
递推公式:
dp[i][j] 分两种情况

  1. 子串长度(j - i)小于等于 2,如 a、aa, 只要起始字符等于结尾字符就是回文串
  2. 子串长度大于 2,如 a…a,在起始字符等于结尾字符的同时,还要保证 … 是回文串再行,而 … 是不是回文串由 dp[i + 1][j - 1] 状态决定。

注意遍历顺序结构: 第一层(起始位置)需要倒着遍历,因为首尾字符相同时,需要查看 i +1 开始 j - 1 结尾的状态值,也就是 dp[i + 1][j - 1] 状态,如果正着遍历,i + 1 下层的状态还没有更新;第二点:i,j 的含义决定第二次遍历顺序应从 j = i 开始,结尾下标 j 应大于等于起始下标 i。
返回值: 回文子串数目另外记录

class Solution {public int countSubstrings(String s) {int len = s.length();boolean[][] dp = new boolean[len][len];int res = 0;for (int i = len - 1; i >= 0; i--) {  // 注意从后向前遍历for (int j = i; j < len; j++) {// 判断首尾字符是否相等if (s.charAt(i) == s.charAt(j)) {// 情况一和情况二合起来写了,简洁一点if (j - i <= 1 || dp[i + 1][j - 1] == true) {dp[i][j] = true;res++;}}// 不相等不用处理,默认为 false}}return res;}
}

方式二:双指针法
先确定中间子串,如果中间子串为回文串,子串区间每次左右各扩大 1。
中间初始子串:由 1 个字符或两个字符组成。

class Solution {public int countSubstrings(String s) {int len = s.length();int res = 0;for (int i = 0; i < len; i++) {// 1 个字符作为中心子串res += extend(s, i, i, len);// 两个字符作为中心子串res += extend(s, i, i + 1, len);}return res;}public int extend(String s, int i, int j, int len) {int result = 0;while (i >= 0 && j < len && s.charAt(i) == s.charAt(j)) {// 不越界情况下,新增首尾两个字符相同,继续扩大区间i--;j++;result++;}return result;}
}

5. 最长回文子串

Leetcode 链接

题解:
和上题类似,这里是求最长回文串
方式一:动态规划
同上题,是回文串时记录最大长度,和最大长度对应的起始末尾下标。

class Solution {public String longestPalindrome(String s) {int len = s.length();boolean[][] dp = new boolean[len][len];int maxLen = 0;int start = 0;int end = 0;for (int i = len - 1; i >= 0; i--) {for (int j = i; j < len; j++) {// 首尾字符相同if (s.charAt(i) == s.charAt(j)) {  // 情况一和情况二if (j - i <= 1 || dp[i + 1][j - 1] == true) {// 当前子串是回文串,更新当前状态dp[i][j] = true;// 回文子串最大长度判断if (j - i + 1 > maxLen) {maxLen = j - i + 1;start = i;end = j;}}}}}return s.substring(start, end + 1);}
}

方式二:双指针

class Solution {public String longestPalindrome(String s) {int size = s.length();// 记录最长回文串的起始下表和结尾下标int start = 0;int end = 0;for (int i = 0; i < size; i++) {int len1 = extend(s, i, i, size);int len2 = extend(s, i, i + 1, size);// 取最大长度情况int len = Math.max(len1, len2);// 判断 start 和 end 是否需要更新if (len > end - start) {// 知道中心串下标 i 和长度求 start 和 end start = i - (len - 1) / 2;end = start + len - 1;}}return s.substring(start, end + 1);}public int extend(String s, int i, int j, int size) {while (i >= 0 && j < size && s.charAt(i) == s.charAt(j)) {i--;j++;}// 注意,abc,i = 0, j = 2 跳出的循环,所以回文串长度应该为 j - i - 1,而不是 j - i + 1。return j - i - 1;}
}

516. 最长回文子序列

Leetcode 链接

题解:
注意这里是子序列,指的是不连续的回文串。
状态 dp[i][j]: 表示下标从 i 到 j 的该子串的最长回文子序列长度
递推公式: 首尾字符相等时 dp[i][j] = dp[i + 1][j - 1] + 2,不相等时dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1])
举个例子:
a…b 时:a 不等于 b,a…b 的最长回文子序列应该的 a… 和 …b 中的最大值。
a…a 时:a 等于 a,a…a 的最长回文子序列应该是 … 的最长回文子序列长度加上 2 (表示首尾新增的这两个 a)。

class Solution {public int longestPalindromeSubseq(String s) {int len = s.length();int[][] dp = new int[len + 1][len + 1];for (int i = 0; i < len; i++) dp[i][i] = 1;for (int i = len - 1; i >= 0; i--) { for (int j = i + 1; j < len; j++) {if (s.charAt(i) == s.charAt(j)) {dp[i][j] = dp[i + 1][j - 1] + 2;} else {dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);}}}return dp[0][len - 1];}
}

132. 分割回文串 II

Leetcode 链接

题解:
131. 分割回文串 是一道回溯题目,在回溯篇有题解
本题在分割数组时用到动态规划,在判断是否回文时也使用动态规划。后者前边题目已经做过多次, 重点在前者,难点在弄清分割和判断回文的下标,所以这里举例说明。

判断回文先使用双指针法。
状态 dp[i]:以 i -1 结尾的子串最小分割次数
例子:aabb
dp 数组:[-1,0,1,2,3]
i 表示 dp 数组下标,i - 1 为子串结尾下标,j 表示新增分割线下标
i = 4 时子串就为 aabb
j = 0: | aabb , aabb 不是回文串 dp[4] 值不变 dp[4] = 3
j = 1:a | abb , abb 不是回文串 dp[4] 值不变 dp[4] = 3
j = 2:aa | bb , bb 是回文串 dp[4] 值取 aa 状态 dp[2] + 1(1 表示分割一次) 和 原来dp[4] 最小值
j = 3:aab | b , b 是回文串 dp[4] 值取 aab 状态 dp[3] + 1 和 原来dp[4] 最小值

初始化每个状态为分割次数最大值:aabb 、dp 数组: [-1,0,1,2,3]

class Solution {public int minCut(String s) {int len = s.length(); int[] dp = new int[len + 1];// 初始化:如: aabb  dp 数组:[-1,0,1,2,3]for (int i = 0; i <= len; i++) {dp[i] = i - 1;}// i = 1 时表示子串为 a ,不用分割,所以 i 从 2 开始for (int i = 2; i <= len; i++) {for (int j = 0; j < i; j ++) {if (isPal(s, j, i - 1)) {dp[i] = Math.min(dp[j] + 1, dp[i]);}}}return dp[len];}// 判断回文public boolean isPal(String s, int start, int end) {while (start < end) {if (s.charAt(start) != s.charAt(end)) {return false;}start++;end--;}return true;}
}

双 dp:

class Solution {public int minCut(String s) {int len = s.length(); int[] dp = new int[len + 1];boolean[][] mat = getMat(s, len);for (int i = 0; i <= len; i++) {dp[i] = i - 1;}for (int i = 2; i <= len; i++) {for (int j = 0; j < i; j++) {if (mat[j][i - 1]) {dp[i] = Math.min(dp[j] + 1, dp[i]);}}}return dp[len];}// 回文串的判断public boolean[][] getMat(String s, int len) {boolean[][] dp = new boolean[len][len];for (int i = len - 1; i >= 0; i--) {for (int j = i; j < len; j++) {if (s.charAt(i) == s.charAt(j)) {if (j - i <= 1 || dp[i + 1][j - 1] == true) {dp[i][j] = true;}}}}return dp;}
}

Leetcode 刷题笔记(三十) ——动态规划篇之子序列问题:回文相关推荐

  1. 小何同学的leetcode刷题笔记 基础篇(01)整数反转

    小何同学的leetcode刷题笔记 基础篇(01)整数反转[07] *** [01]数学取余法*** 对数字进行数位操作时,常见的方法便是用取余的方法提取出各位数字,再进行操作 操作(1):对10取余 ...

  2. 【leetcode刷题笔记】动态规划

    #[leetcode刷题笔记]动态规划 石子游戏 public boolean stoneGame(int[] piles) {int N = piles.length;// dp[i][j] is ...

  3. LeetCode刷题笔记-动态规划-day4

    文章目录 LeetCode刷题笔记-动态规划-day4 55. 跳跃游戏 1.题目 2.解题思路 3.代码 45. 跳跃游戏 II 1.题目 2.解题思路 3.代码 LeetCode刷题笔记-动态规划 ...

  4. LeetCode刷题笔记- 15.三数之和

    LeetCode刷题笔记- 15.三数之和 C语言 题目 注意点 C语言 /*** Return an array of arrays of size *returnSize.* The sizes ...

  5. LeetCode刷题笔记(算法思想 四)

    LeetCode刷题笔记(算法思想 四) 七.动态规划 斐波那契数列 70. 爬楼梯 198. 打家劫舍 213. 打家劫舍 II 信件错排 母牛生产 矩阵路径 64. 最小路径和 62. 不同路径 ...

  6. 刷题笔记(十四)--二叉树:层序遍历和DFS,BFS

    目录 系列文章目录 前言 题录 102. 二叉树的层序遍历 BFS DFS_前序遍历 107. 二叉树的层序遍历 II BFS DFS 199. 二叉树的右视图 BFS DFS 637. 二叉树的层平 ...

  7. LeetCode刷题笔记汇总

    LeetCode刷题笔记汇总 第一次刷LeetCode写的一些笔记. 1.两数之和 3.无重复字符的最长子串 15.三数之和 18.四数之和 19.删除链表的倒数第 N 个结点 20.有效的括号 21 ...

  8. leetcode刷题笔记——二分查找

    leetcode刷题笔记--二分查找 目前完成的贪心相关的leetcode算法题序号: 中等:80,81 困难:4 来源:力扣(LeetCode) 链接:https://leetcode-cn.com ...

  9. 卷进大厂系列之LeetCode刷题笔记:二分查找(简单)

    LeetCode刷题笔记:二分查找(简单) 学算法,刷力扣,加油卷,进大厂! 题目描述 涉及算法 题目解答 学算法,刷力扣,加油卷,进大厂! 题目描述 力扣题目链接 给定一个 n 个元素有序的(升序) ...

  10. leetcode刷题(三)——容斥原理

    leetcode刷题系列三.这一节的内容主要是容斥原理的题目和题解. 百度百科上容斥原理的解释: 在计数时,必须注意没有重复,没有遗漏.为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法 ...

最新文章

  1. php能实现文本复制吗,php 简单复制文件的方法
  2. 基于 RT-Thread赛车控制算法开发
  3. 使用ISAPI_Rewrite做实用的重定向
  4. Leetcode: Populating Next Right Pointers in Each Node II
  5. 百分点大数据技术团队:数据治理“PAI”实施方法论
  6. java线程池,信号量使用demo
  7. C/C++信息隐写术(四)之大程序藏入BMP文件
  8. 马氏距离详解(数学原理、适用场景、应用示例代码)
  9. OpenCV3学习(7.1)——图像分割之一(漫水填充FloodFill)
  10. CentOS系统缺少库文件解决办法
  11. php 修改最大上传,php 修改上传文件大小限制实例详解
  12. My97 DatePicker 选择时间后弹出选择的时间
  13. nginx封锁恶意IP,并且定时取消的两种脚本
  14. 有关单片机驱动IR2104遇到的问题及解决方法
  15. Git之深入解析如何解决.git目录过大的问题
  16. wps启用编辑按钮在哪里_wps页面设置在哪里?wps页面设置使用教程
  17. ActivityManagerService分析
  18. 视频编码c语言,MPEG4codec(c) MPEG4视频格式的编解码源码 C语言实现 - 下载 - 搜珍网...
  19. android触摸屏映射,解决android4.0 触摸屏分辨率映射不准
  20. leetcode 58. 最后一个单词的长度(Length of Last Word)

热门文章

  1. 【SimpleITK】使用区域生长法/种子填充法/形态学分割肺-CT img
  2. C++中派生类的构造函数
  3. oracle的单行函数,Oracle中单行函数之(通用函数)
  4. Ubuntu-vim 命令
  5. 将 url query参数 字符串转换为JSON 对象
  6. PPT中均匀分布各图形(水平或垂直)
  7. Android报错:IllegalStateException: The specified child already has a parent问题解决办法
  8. JSP — 项目篇《I》【打印九九乘法表】
  9. 【推荐】 Neutralizer 安卓上特殊的均衡器
  10. 2018-12-13丛晓强作业