LeetCode:Palindrome Partitioning,Palindrome Partitioning II
LeetCode:Palindrome Partitioning
题目如下:(把一个字符串划分成几个回文子串,枚举所有可能的划分)
Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = "aab",
Return
[
["aa","b"],
["a","a","b"]
]
分析:首先对字符串的所有子串判断是否是回文,设f[i][j] = true表示以i为起点,长度为j的子串是回文,等于false表示不是回文,那么求f[i][j]的动态规划方程如下:
当j = 1,f[i][j] = true;
当j = 2,f[i][j] = (s[i]==s[i+1]),其中s是输入字符串
当j > 2, f[i][j] = f[i+1][j-2] && (s[i] == s[i+j-1])(即判断s[m..n]是否是回文时:只要s[m+1...n-1]是回文并且s[m] = s[n],那么它就是回文,否则不是回文)
这一题也可以不用动态规划来求f,可以用普通的判断回文的方式判断每个子串是否为回文。 本文地址
求得f后,根据 f 可以构建一棵树,可以通过DFS来枚举所有的分割方式,代码如下:
class Solution {
public:
vector<vector<string>> partition(string s) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
vector< vector<string> >res;
int len = s.length();
if(len == )return res;
//f[i][j] = true表示以i为起点,长度为j的子串是回文
bool **f = new bool*[len];
for(int i = ; i < len; i++)
{
f[i] = new bool[len+];
for(int j = ; j < len+; j++)
f[i][j] = ;
f[i][] = true;
}
for(int k = ; k <= len; k++)
{
for(int i = ; i <= len-k; i++)
{
if(k == )f[i][] = (s[i] == s[i+]);
else f[i][k] = f[i+][k-] && (s[i] == s[i+k-]);
}
}
vector<string> tmp;
DFSRecur(s, f, , res, tmp);
for(int i = ; i < len; i++)
delete [](f[i]);
delete []f;
return res;
}
void DFSRecur(const string &s, bool **f, int i,
vector< vector<string> > &res, vector<string> &tmp)
{//i为遍历的起点
int len = s.length();
if(i >= len){res.push_back(tmp); return;}
for(int k = ; k <= len - i; k++)
if(f[i][k] == true)
{
tmp.push_back(s.substr(i, k));
DFSRecur(s, f, i+k, res, tmp);
tmp.pop_back();
}
}
};
LeetCdoe:Palindrome Partitioning II
题目如下:(在上一题的基础上,找出最小划分次数)
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut. 本文地址
算法1:在上一题的基础上,我们很容易想到的是在DFS时,求得树的最小深度即可(遍历时可以根据当前求得的深度进行剪枝),但是可能是递归层数太多,大数据时运行超时,也贴上代码:
class Solution {
public:
int minCut(string s) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
int len = s.length();
if(len <= )return ;
//f[i][j] = true表示以i为起点,长度为j的子串是回文
bool **f = new bool*[len];
for(int i = ; i < len; i++)
{
f[i] = new bool[len+];
for(int j = ; j < len+; j++)
f[i][j] = ;
f[i][] = true;
}
for(int k = ; k <= len; k++)
{
for(int i = ; i <= len-k; i++)
{
if(k == )f[i][] = (s[i] == s[i+]);
else f[i][k] = f[i+][k-] && (s[i] == s[i+k-]);
}
}
int res = len, depth = ;
DFSRecur(s, f, , res, depth);
for(int i = ; i < len; i++)
delete [](f[i]);
delete []f;
return res - ;
}
void DFSRecur(const string &s, bool **f, int i,
int &res, int &currdepth)
{
int len = s.length();
if(i >= len){res = res<=currdepth? res:currdepth; return;}
for(int k = ; k <= len - i; k++)
if(f[i][k] == true)
{
currdepth++;
if(currdepth < res)
DFSRecur(s, f, i+k, res, currdepth);
currdepth--;
}
}
};
算法2:设f[i][j]是i为起点,长度为j的子串的最小分割次数,f[i][j] = 0时,该子串是回文,f的动态规划方程是:
f[i][j] = min{f[i][k] + f[i+k][j-k] +1} ,其中 1<= k <j
这里f充当了两个角色,一是记录子串是否是回文,二是记录子串的最小分割次数,可以结合上一题的动态规划方程,算法复杂度是O(n^3), 还是大数据超时,代码如下:
class Solution {
public:
int minCut(string s) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
int len = s.length();
if(len <= )return ;
//f[i][j] = true表示以i为起点,长度为j的子串的最小切割次数
int **f = new int*[len];
for(int i = ; i < len; i++)
{
f[i] = new int[len+];
for(int j = ; j < len+; j++)
f[i][j] = len;
f[i][] = ;
}
for(int k = ; k <= len; k++)
{
for(int i = ; i <= len-k; i++)
{
if(k == && s[i] == s[i+])f[i][] = ;
else if(f[i+][k-] == &&s[i] == s[i+k-])f[i][k] = ;
else
{
for(int m = ; m < k; m++)
if(f[i][k] > f[i][m] + f[i+m][k-m] + )
f[i][k] = f[i][m] + f[i+m][k-m] + ;
}
}
}
int res = f[][len], depth = ;
for(int i = ; i < len; i++)
delete [](f[i]);
delete []f;
return res;
}
};
算法3:同上一题,用f来记录子串是否是回文,另外优化最小分割次数的动态规划方程如下,mins[i] 表示子串s[0...i]的最小分割次数:
- 如果s[0...i]是回文,mins[i] = 0
- 如果s[0...i]不是回文,mins[i] = min{mins[k] +1 (s[k+1...i]是回文) 或 mins[k] + i-k (s[k+1...i]不是回文)} ,其中0<= k < i
代码如下,大数据顺利通过,结果Accept: 本文地址
class Solution {
public:
int minCut(string s) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
int len = s.length();
if(len <= )return ;
//f[i][j] = true表示以i为起点,长度为j的子串是回文
bool **f = new bool*[len];
for(int i = ; i < len; i++)
{
f[i] = new bool[len+];
for(int j = ; j < len+; j++)
f[i][j] = false;
f[i][] = true;
}
int mins[len];//mins[i]表示s[0...i]的最小分割次数
mins[] = ;
for(int k = ; k <= len; k++)
{
for(int i = ; i <= len-k; i++)
{
if(k == )f[i][] = (s[i] == s[i+]);
else f[i][k] = f[i+][k-] && (s[i] == s[i+k-]);
}
if(f[][k] == true){mins[k-] = ; continue;}
mins[k-] = len - ;
for(int i = ; i < k-; i++)
{
int tmp;
if(f[i+][k-i-] == true)tmp = mins[i]+;
else tmp = mins[i]+k-i-;
if(mins[k-] > tmp)mins[k-] = tmp;
}
}
for(int i = ; i < len; i++)
delete [](f[i]);
delete []f;
return mins[len-];
}
};
【版权声明】转载请注明出处:http://www.cnblogs.com/TenosDoIt/p/3421283.html
LeetCode:Palindrome Partitioning,Palindrome Partitioning II的更多相关文章
- [LeetCode] 680. Valid Palindrome II 验证回文字符串 II
Given a non-empty string s, you may delete at most one character. Judge whether you can make it a pa ...
- [LeetCode] 214. Shortest Palindrome 最短回文串
Given a string s, you are allowed to convert it to a palindrome by adding characters in front of it. ...
- LeetCode 1216. Valid Palindrome III
原题链接在这里:https://leetcode.com/problems/valid-palindrome-iii/ 题目: Given a string s and an integer k, f ...
- [LeetCode] 409. Longest Palindrome 最长回文
Given a string which consists of lowercase or uppercase letters, find the length of the longest pali ...
- leetcode bug & 9. Palindrome Number
leetcode bug & 9. Palindrome Number bug shit bug "use strict"; /** * * @author xgqfrms ...
- leetcode 第九题 Palindrome Number(java)
Palindrome Number time=434ms 负数不是回文数 public class Solution { public boolean isPalindrome(int x) { in ...
- leetcode@ [131/132] Palindrome Partitioning & Palindrome Partitioning II
https://leetcode.com/problems/palindrome-partitioning/ Given a string s, partition s such that every ...
- 乘风破浪:LeetCode真题_040_Combination Sum II
乘风破浪:LeetCode真题_040_Combination Sum II 一.前言 这次和上次的区别是元素不能重复使用了,这也简单,每一次去掉使用过的元素即可. 二.Combination Sum ...
- [LeetCode] 445. Add Two Numbers II 两个数字相加之二
You are given two linked lists representing two non-negative numbers. The most significant digit com ...
随机推荐
- OOD沉思录 --- 类和对象的关系 --- 包含关系4
4.9 在实现语义约束时,最好根据类定义来实现.但是这经常会导致泛滥成灾的类,在这种情况下约束应当在类的行为中实现,通常在类的构造函数中实现,但不是必须如此. 还是以汽车为例,我们看汽车的定义,为了集 ...
- 优秀的PHP开源项目集合
包管理Package Management Package Management Related 框架 框架组件 微框架Micro Frameworks 内容管理系统Content Managemen ...
- InfluxDB Cli中查询结果中time格式显示设置
InfluxDB Cli中,time默认显示为19位时间戳格式,平时查询起来特不方便,那么,如何设置成为我们人类能看懂的时间格式呢? 方法有二: 1.$ influx -precision rfc33 ...
- oracle归档日志写满错误解决方法
最近一年,手头上负责的项目要部署到很多个地方,由于项目组里没有人对oracle比较熟悉,只能给自己增加一个DBA的角色了.由于短时间内要部署很多单位,备份策略没有设置好,结果过了一个月,用户报告程序开 ...
- PHP笔记(PHP高级篇)
高级篇中将涉及数据库的使用以及Cookie和Session会话,提高PHP的开发效率和运行效率 PHP程序员需要掌握的MySQL操作 为项目设计表 使用SQL语句 MySQL的目录结构 data目录中 ...
- javascript 特效实现(3)—— 鼠标滑过显示二级菜单效果
1. 关键代码:使用 switch 或 if 判断语句,改变对应的二级菜单显示方式为 block 或 none function selectTabMenu(i){ switch(i){ case 7 ...
- sass+compass+bootstrap三剑合璧高效开发记录
1. 先搭建环境,下载node.js,rubyinstaller,安装, 安装rubyinstaller时,要选上include system path,这样就会自动将node.js执行添加到wind ...
- linux下开启SSH,并且允许root用户远程登录,允许无密码登录
参考:http://blog.csdn.net/jia0511/article/details/8237698 1. 允许root用户远程登录 修改ssh服务配置文件 sudo vi /etc/ssh ...
- android:layout_gravity和android:gravity的区别
1.首先来看看android:layout_gravity和android:gravity的使用区别. android:gravity: 这个是针对控件里的元素来说的,用来控制元素在该控件里的显示位置 ...
- mysql日志类型
在MySQL中共有4中日志:错误日志.二进制日志.查询日志和慢查询日志 一.错误日志 错误日志名 host_name.err,并默认在参数DATADIR指定的目录中写入日志文件.可使用 --log-e ...