Leetcode: Palindrome Partitioning II
参考:http://www.cppblog.com/wicbnu/archive/2013/03/18/198565.html
我太喜欢用dfs和回溯法了,但是这些暴力的方法加上剪枝之后复杂度依然是很高,显然不能达到题目的要求。
这个时候应该考虑动态规划,并且要复杂度尽量接近O(n^2)的算法。
下面这个方法更加简洁:自长到短找到回文串后,往后dfs,并记录递归深度表示并更新最小划分数。http://fisherlei.blogspot.com/2013/03/leetcode-palindrome-partitioning-ii.html
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.
题解:
类似矩阵连乘的动归思路。
dp[i][j]=min(dp[i][k]+dp[k+1][j]+1), i<=k<j.
但是用这个方程的时间是O(n^3),简化dp[i][j]为dp[i],表示从0到i的minCut.
dp[i]=min(dp[k]+1, dp[k]+i-k), 0<=k<i.
(s[k+1, i]是回文串) (s[k+1, i]不是回文串)
具体代码参见上述链接。
值得注意的是,计算是否为回文数的过程中也要用记忆化搜索才能减少重复比较的次数,it's smart~
MY CODE:
//
// ParlindromePartitioningII.cpp
// SJMcode
//
// Created by Jiamei Shuai on 13-8-31.
// Copyright (c) 2013年 Jiamei Shuai. All rights reserved.
// #include <vector>
#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std; // 两处优化:
// 1.已经计算过的区间的最短划分次数用map纪录
// 2.回文串的判断结果也要用map记录 class Solution{
public:
int *minCutMat;
vector<vector<int> > map; int IsPalindrome(string &s, int i, int j)
{
if(i>j) return false;
if(map[i][j]!= -)
return map[i][j];
if(i==j)
return map[i][j]=; if(s[i]!=s[j])
return map[i][j]=;
else{
if(j-i==)
return map[i][j]=;
else
return map[i][j]=IsPalindrome(s,i+,j-);
}
} int minCut(string s) // 动态规划 d[i] = min{d[k]+1, d[k]+i-k}, 0<=k<i
{
int n = (int)s.length();
if(n==||n==)
return ; vector<int> min, vtmp;
min.clear();vtmp.clear();map.clear();
for(int i=; i<s.size(); i++)
{
min.push_back();
vtmp.push_back(-);
}
for(int i=; i<s.size(); i++)
map.push_back(vtmp); int tmp, ans;
for(int inter = ; inter<n; inter++)
{
if(IsPalindrome(s, , inter))
min[inter]=;
else{
ans = n+;
for(int k = ; k < inter; k++)
{
if(IsPalindrome(s, k+, inter))
tmp = min[k]+;
else
tmp = min[k] + inter - k;
if(tmp < ans)
ans = tmp;
}
min[inter] = ans;
}
}
return min[n-];
} // 较复杂的算法用dfs或者回溯法都太慢了,加上了所有的剪枝策略还是会超时
// 这种情况大多数都应该使用动态规划,要多总结,少犯错误。 int minCut2(string s) // 总是超时,复杂度太高
//这个方法相当于类似矩阵链乘的算法,dp[i][j] = min(dp[i][k]+dp[k+1][j]), i<=k<j,复杂度是O(n^3)
//可以简化dp[i][j]为dp[i],表示从0到i的minCut
{
int minCutNum = (int)s.size();
int len = (int)s.size(); minCutMat = new int[len*len]; // 注意new int[]而不是()
memset(minCutMat, -, len*len*sizeof(int)); vector<int> vtmp;
vtmp.clear();map.clear();
for(int i=; i<s.size(); i++)
vtmp.push_back(-);
for(int i=; i<s.size(); i++)
map.push_back(vtmp); // Notice: if the string need no split and itself a palindrome, how to handle it? 注意细节
if(IsPalindrome(s, , len-)) return ; split(s, , len-, minCutNum); delete []minCutMat; return minCutNum;
} int split(string &s, int begin, int end, int &minCutNum)
{
if(begin == end) return ; if(IsPalindrome(s, begin, end)) return ; int minCurrentSplit = (int)s.size();
int left,right; for(int i = begin; i < end; i++)
{
assert(begin*s.size()+i < s.size()*s.size());
assert(begin*s.size()+i < s.size()*s.size());
if(minCutMat[begin*s.size()+i] >= )
left = minCutMat[begin*s.size()+i];
else
{
left = split(s, begin, i, minCutNum);
minCutMat[begin*s.size()+i] = left;
}
if(left >= minCutNum) { return <<;} if(minCutMat[(i+)*s.size()+end] >= )
right = minCutMat[(i+)*s.size()+end];
else
{
right = split(s, i+, end, minCutNum);
minCutMat[(i+)*s.size()+end] = right;
}
if(right >= minCutNum) return <<; int tmp = left + + right; minCurrentSplit = min(tmp, minCurrentSplit); if(begin == && end == s.size()-) // outer loop
minCutNum = min(tmp, minCutNum);
}
return minCurrentSplit;
} }; int main()
{
Solution sln;
cout << sln.minCut("apjesgpsxoeiokmqmfgvjslcjukbqxpsobyhjpbgdfruqdkeiszrlmtwgfxyfostpqczidfljwfbbrflkgdvtytbgqalguewnhvvmcgxboycffopmtmhtfizxkmeftcucxpobxmelmjtuzigsxnncxpaibgpuijwhankxbplpyejxmrrjgeoevqozwdtgospohznkoyzocjlracchjqnggbfeebmuvbicbvmpuleywrpzwsihivnrwtxcukwplgtobhgxukwrdlszfaiqxwjvrgxnsveedxseeyeykarqnjrtlaliyudpacctzizcftjlunlgnfwcqqxcqikocqffsjyurzwysfjmswvhbrmshjuzsgpwyubtfbnwajuvrfhlccvfwhxfqthkcwhatktymgxostjlztwdxritygbrbibdgkezvzajizxasjnrcjwzdfvdnwwqeyumkamhzoqhnqjfzwzbixclcxqrtniznemxeahfozp"); return ;
}
附上更简洁的算法:
1: int minCut(string s) {
: int len = s.size();
: int D[len+];
: bool P[len][len];
: //the worst case is cutting by each char
: for(int i = ; i <= len; i++)
: D[i] = len-i;
: for(int i = ; i < len; i++)
: for(int j = ; j < len; j++)
: P[i][j] = false;
: for(int i = len-; i >= ; i--){
: for(int j = i; j < len; j++){
: if(s[i] == s[j] && (j-i< || P[i+][j-])){
: P[i][j] = true;
: D[i] = min(D[i],D[j+]+);
: }
: }
: }
: return D[]-;
: }
以及使用回溯+剪枝的方法:
: int minCut(string s) {
: int min = INT_MAX;
: DFS(s, , , min);
: return min;
: }
: void DFS(string &s, int start, int depth, int& min)
: {
: if(start == s.size())
: {
: if(min> depth-)
: min = depth-;
: return;
: }
: for(int i = s.size()-; i>=start; i--) //find the biggest palindrome first
: {
: if(isPalindrome(s, start, i))
: {
: DFS(s, i+, depth+, min);
: }
:
:
: }
: }
: bool isPalindrome(string &s, int start, int end)
: {
: while(start< end)
: {
: if(s[start] != s[end])
: return false;
: start++; end--;
: }
: return true;
: }
总结下来,要学会分析问题,不能一成不变的只用一个算法,可能会非常低效。
Leetcode: Palindrome Partitioning II的更多相关文章
- [LeetCode] Palindrome Partitioning II 解题笔记
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- LeetCode: Palindrome Partitioning II 解题报告
Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...
- [LeetCode] Palindrome Partitioning II 拆分回文串之二
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- [leetcode]Palindrome Partitioning II @ Python
原题地址:https://oj.leetcode.com/problems/palindrome-partitioning-ii/ 题意: Given a string s, partition s ...
- LeetCode:Palindrome Partitioning,Palindrome Partitioning II
LeetCode:Palindrome Partitioning 题目如下:(把一个字符串划分成几个回文子串,枚举所有可能的划分) Given a string s, partition s such ...
- leetcode@ [131/132] Palindrome Partitioning & Palindrome Partitioning II
https://leetcode.com/problems/palindrome-partitioning/ Given a string s, partition s such that every ...
- 【leetcode】Palindrome Partitioning II
Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...
- leetcode 131. Palindrome Partitioning 、132. Palindrome Partitioning II
131. Palindrome Partitioning substr使用的是坐标值,不使用.begin()..end()这种迭代器 使用dfs,类似于subsets的题,每次判断要不要加入这个数 s ...
- 【LeetCode】132. Palindrome Partitioning II
Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...
随机推荐
- ADB
adb logcat 命令详解 log过滤 http://blog.csdn.net/liao277218962/article/details/50129009 如何使用 adb logcat 查看 ...
- EFCore教程
https://docs.microsoft.com/en-us/ef/core/modeling/alternate-keys aspnet core 教程 https://docs.microso ...
- nginx配置杂记
1.一个接口的形式要求是:IP+端口,并且通信协议类型是:https,如何做域名解析: ①设置一个端口.同时在防火墙中打开这个端口,重启防火墙: ②在服务器上/etc/nginx/conf.d的目录下 ...
- (转)CentOS下开机启动查看管理命令:chkconfig用法
CentOS下开机启动查看管理命令:chkconfig用法 CentOS下开机启动查看管理的命令是:chkconfig 1. 开机启动列表查看: chkconfig --list 说明 ...
- 【转】MySQL性能优化的最佳21条经验
文章转自: http://blog.csdn.net/waferleo/article/details/7179009 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关 ...
- Beta阶段项目总结
1. 每个成员在beta 阶段的实践和alpha 阶段有何改进? 王文奇:对数据库的操作更为熟练,在java web中实现对数据库的修改更加完善 刘元柱:对javascript,css和servl ...
- highcharts饼状图使用案例
在公司由于需要对订单数据进行分析,故使用到了highcharts工具 <block name="Js"> <script type="text/java ...
- 在js中实现邮箱格式的验证
在js中实现邮箱格式的验证 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><htm ...
- struts2使用annotation注意事项
struts2使用annotation注意事项 1.包名只能以.action .actions .struts .struts2结尾.如:com.cnbolgs.web.actions 2.类名只 ...
- 解决svn问题:Wrong committed revision number: -1
参考:http://my.oschina.net/luckyi/blog/291007