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 ...
随机推荐
- FlumeNG 笔记
环境:CentOS6.6 64位 + FlumeNG 1.6 请参考推荐文档: Flume-ng的原理和使用 - JunezChen Blog - SegmentFault https://segm ...
- hibernate学习一(hibernate简介与准备)
一.hibernate简介 Hibernate是一个开放源代码的对象-关系映射(Object/Relational Mapping 即 ORM)框架,它对JDBC进行了非常轻量级的对象封装,它将POJ ...
- Spring的简单demo
---------------------------------------- 开发一个Spring的简单Demo,具体的步骤如下: 1.构造一个maven项目 2.在maven项目的pom.xml ...
- 5. web前端开发分享-css,js深化篇
一. css练习网易专题: 1. http://news.163.com/ 新闻 跟腾讯的新闻版式大体没有大的变化,只是细节. 2. http://news.163.com/photo/#Curren ...
- 谈谈混合 App Web 资源的打包与增量更新
综述 移动 App 的运行环境具有带宽不稳定,流量收费,启动速度比较重要等特点,所以混合 App 如何加载 Web 资源并不是一个新问题.本文目的是总结出一种资源打包下载的思路和方案,并且提供一种打包 ...
- Sql Cursor example
USE [EUC]GO/****** Object: StoredProcedure [dbo].[SP_SME_QueryAuditLog] Script Date: 02/05/2015 ...
- MAC OS升级到10.11(OS X EICAPTION)之后CocoaPods不能正常使用的问题解决
昨晚回家之后开始升级系统到10.11,下载了一整个晚上之后终于在早上下载完毕,早上带到公司,想查一个第三方库的时候却遇到了问题: guoyufudeMacBook-Pro:~ GuoYufu$ pod ...
- 第3月第15天 afconvert lame
1. //CAF 转换成MP3 (可以) afconvert -f mp4f -d aac -b 128000 /Users/amarishuyi/Desktop/sound1.caf/Users/a ...
- linux 下串口独占方式打开
参考文章: http://blog.csdn.net/rl529014/article/details/51336161 http://blog.csdn.net/lin_fs/article/de ...
- Web获取客户端物理MAC地址(ocx插件)
主要是通过ActiveX控件 从本地获取到MAC地址,传入到浏览器打开的网页中,再提交到服务器. 具体详解与步骤看文档中: 文件实例包下载 DotNetFX 文件夹附件文件:(可能安装时需用) dot ...