力扣132. 分割回文串 II-C语言实现-困难题
题目(真心不会)
传送门
文本
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
示例 1:
输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
示例 2:
输入:s = "a"
输出:0
示例 3:
输入:s = "ab"
输出:1
提示:
1 = s.length = 2000
s 仅由小写英文字母组成
来源:力扣(LeetCode)
模板
int minCut(char * s){
}
解题
分析
设 f[i]f[i]f[i] 表示字符串的前缀 s[0..i]s[0..i]s[0..i] 的最少分割次数。要想得出 f[i]f[i]f[i] 的值,我们可以考虑枚举 s[0..i]s[0..i]s[0..i] 分割出的最后一个回文串,这样我们就可以写出状态转移方程:
f[i]=min?0≤ji{f[j]}+1,其中 s[j+1..i] 是一个回文串f[i] = \min_{0 \leq j i} { f[j] } + 1, \quad 其中 ~ s[j+1..i] ~是一个回文串 f[i]=0≤jimin?{f[j]}+1,其中 s[j+1..i] 是一个回文串
即我们枚举最后一个回文串的起始位置 j+1j+1j+1,保证 s[j+1..i]s[j+1..i]s[j+1..i] 是一个回文串,那么 f[i]f[i]f[i] 就可以从 f[j]f[j]f[j] 转移而来,附加 111 次额外的分割次数。
注意到上面的状态转移方程中,我们还少考虑了一种情况,即 s[0..i]s[0..i]s[0..i] 本身就是一个回文串。此时其不需要进行任何分割,即:
f[i]=0f[i] = 0 f[i]=0
那么我们如何知道 s[j+1..i]s[j+1..i]s[j+1..i] 或者 s[0..i]s[0..i]s[0..i] 是否为回文串呢我们可以使用与「131. 分割回文串的官方题解」中相同的预处理方法,将字符串 sss 的每个子串是否为回文串预先计算出来,即:
设 g(i,j)g(i, j)g(i,j) 表示 s[i..j]s[i..j]s[i..j] 是否为回文串,那么有状态转移方程:
g(i,j)={True,i≥jg(i+1,j?1)∧(s[i]=s[j]),otherwiseg(i, j) = \begin{cases} \texttt{True}, \quad i \geq j \ g(i+1,j-1) \wedge (s[i]=s[j]), \quad \text{otherwise} \end{cases} g(i,j)={True,g(i+1,j?1)∧(s[i]=s[j]),?i≥jotherwise?
其中 ∧\wedge∧ 表示逻辑与运算,即 s[i..j]s[i..j]s[i..j] 为回文串,当且仅当其为空串(ijijij),其长度为 111(i=ji=ji=j),或者首尾字符相同且 s[i+1..j?1]s[i+1..j-1]s[i+1..j?1] 为回文串。
这样一来,我们只需要 O(1)O(1)O(1) 的时间就可以判断任意 s[i..j]s[i..j]s[i..j] 是否为回文串了。通过动态规划计算出所有的 fff 值之后,最终的答案即为 f[n?1]f[n-1]f[n?1],其中 nnn 是字符串 sss 的长度。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii/solution/fen-ge-hui-wen-chuan-ii-by-leetcode-solu-norx/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
完整源码
传送门
int minCut(char* s) {
int n = strlen(s);
bool g[n][n];
memset(g, 1, sizeof(g));
for (int i = n - 1; i = 0; --i) {
for (int j = i + 1; j n; ++j) {
g[i][j] = (s[i] == s[j]) g[i + 1][j - 1];
}
}
int f[n];
for (int i = 0; i n; ++i) {
f[i] = INT_MAX;
}
for (int i = 0; i n; ++i) {
if (g[0][i]) {
f[i] = 0;
} else {
for (int j = 0; j i; ++j) {
if (g[j + 1][i]) {
f[i] = fmin(f[i], f[j] + 1);
}
}
}
}
return f[n - 1];
}
运行结果
力扣132. 分割回文串 II-C语言实现-困难题 相关文章
【题解】力扣765. 情侣牵手
765. 情侣牵手 题目来源 765. 情侣牵手 思路 如果一对情侣恰好坐在了一起,并且坐在了成组的座位上,其中一个下标一定是偶数,另一个一定是奇数,并且「偶数的值 + 1 = 奇数的值」。例如编号数对 [2, 3] 、 [9, 8] ,这些数对的特点是除以 2(下取整)得到的
二叉树的右视图和先重建二叉树,再打印二叉树的右视图(力扣199题、NC136题)
199.二叉树的右视图 ?给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 输入:[1,2,3,null,5,null,4]输出:[1, 3, 4]解释: 1 --- / \2 3 --- \ \ 5 4 --- 利用层次遍历寻找二叉树中的右视图(层次遍历,一次外循
07. 重建二叉树
题目 力扣-剑指 Offer 07. 重建二叉树 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 例如,给出前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7]返回如下的二叉树:
二分图基础
概念 二分图定义 : 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。 二分图概念 : 当且仅当图中不含奇数环。 奇数环
剑指 Offer 06. 从尾到头打印链表
题目 力扣-剑指 Offer 05. 替换空格 请实现一个函数,把字符串 s 中的每个空格替换成%20。 示例 1:输入:s = We are happy.输出:We%20are%20happy. 限制:0 = s 的长度 = 10000 题解 该题难度为简单。 解法一:两个for循环 1,先声明两个整型数组; 2,第一
webpack高级概念,CSS文件的代码分割 与压缩(系列八)
我们之前写的css文件都会被打包进js文件中,要想把css单独打包成一个css文件该怎么做呢 这个时候就需要用到 MiniCssExtractPlugin 开发环境用不到这个功能(因为这个东西不支持热模块更新,样式更改自动替换,不用刷新页面), 一般都是用在生产环境中 。 安
刷题-力扣-503
503. 下一个更大元素 II 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/next-greater-element-ii/ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 题目描述 给定一个循环数组(最后一个元素的下一个元素
力扣503. 下一个更大元素 II-C语言实现-中等难度题
题目 传送门 文本 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不
刷题-力扣-232
232. 用栈实现队列 题目链接 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/implement-queue-using-stacks/ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 题目描述 请你仅使用两个栈实现先入先出队列。队列应当
剑指 Offer 07. 重建二叉树
题目 力扣-剑指 Offer 07. 重建二叉树 输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 例如,给出前序遍历 preorder =[3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7]返回如下的二叉树: