Palindrome Partitioning II
来源:互联网 发布:阿里云基础服务平台图 编辑:程序博客网 时间:2024/06/08 18:59
题目
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.
思路一
用递归得到所有可能的划分,可以参考上篇博文Palindrome Partitioning,然后求取最短的划分。
但是我们没必要存取所有的划分结果,只需要存储划分段数就可以了。
对空间的改进
class Solution {public: int minCut(string s) { // Start typing your C/C++ solution below // DO NOT write int main() function int len = s.length(); if(len<1) return 0; vector<string> vec; int min = INT_MAX; mypart(vec, 0, s, min); return min-1; } void mypart(vector<string> &vec, int cur, string &S, int &min) { if(cur==S.length()) { if(vec.size()<min) min = vec.size(); return ; } for(int i=cur;i<S.length();i++) { int len = i-cur+1; string str = S.substr(cur,len); if(ispalind(str)) { vec.push_back(str); mypart(vec, i+1, S, min); vec.pop_back(); } } } bool ispalind(string &S) { if(S.empty()) return true; int i=0, j=S.length()-1; while(i<j) { if(S[i]!=S[j]) return false; i++; j--; } return true; } };
对大数据虽然没有内存限制了,但是还是出现了 Run Status: Time Limit Exceeded
因为我们还可以进一步的 剪枝优化 步的:如果当前子字符串生成的回文划分段数已经超过了 min ,就没必要接着进行下去了。
剪枝优化时间
for(int i=cur;i<S.length();i++) { int len = i-cur+1; string str = S.substr(cur,len); if(vec.size()<=min && ispalind(str)) { vec.push_back(str); mypart(vec, i+1, S, min); vec.pop_back(); } }
或者
if(vec.size()+1>min) return ; for(int i=cur;i<S.length();i++) { int len = i-cur+1; string str = S.substr(cur,len); if(ispalind(str)) { vec.push_back(str); mypart(vec, i+1, S, min); vec.pop_back(); } }
但好像都还是未能通过大数据。
原因是 虽然加入剪枝,但是算法的基本思想还是遍历,数量级未改变,依旧是 O(N*N) 。
下面考虑要降低数量级了。
思路二
用DP动态规划的思想:
二维标志数组 ispalin[i][j] 记录 s 的 i~j 子串是否是回文的;
一维数组 num[i] 记录 s 的 i~len-1 分割后的最小段数,初始化时 num[0]=len, ... , num[len-1]=1;
最优结果是 num[0]-1 。
动态规划过程:
(1)如果s[i]=s[j] 并且 ispalin[i+1][j-1]=true ,则表示 i~j 也是回文,即 ispalin[i][j]=true。
(2)如果s[i]=s[j] 并且 ispalin[i][j]=true,则 num[i] = min(num[i], num[j+1]+1) ,即更新当前 i~len-1子串的最小段数。
class Solution {public: int minCut(string s) { // Start typing your C/C++ solution below // DO NOT write int main() function int len = s.length(); if(len<2) return 0; vector<vector<bool>> ispalin(len,vector<bool>(len,false)); vector<int> num(len+1,0); for(int i=0;i<len;i++) num[i] = len-i; for(int i=len-1;i>=0;i--) { for(int j=i;j<len;j++) { if(s[i]==s[j]) { if(j-i<2) { ispalin[i][j]=true; num[i] = min(num[i],num[j+1]+1); }else if(ispalin[i+1][j-1]) { ispalin[i][j]=true; num[i] = min(num[i],num[j+1]+1); } } } } return num[0]-1; }};
其实时间复杂度也是 O(N*N)的,但是对大数据轻松通过了。
与思路一比较:
优点在,对当前的子串是否是回文的判断上要更优,避免重复判断。
例如:如果 s1=abba 是回文,当增加长度时 s2=dabbad ,
思路一:再遍历一遍 s2 ,时间 O(length(s2))
思路二:比较新增加的字符是否相等,同时判断s1是否是回文,时间O(2+1)
所以高下优劣立见。
如果仔细分析计算:
(1)思路一的时间复杂度是 O(N*N*length(str))
(2)DP的时间复杂度是 O(N*N*2)
- LeetCode : Palindrome Partitioning II
- [leetcode] Palindrome Partitioning II
- leetcode:Palindrome Partitioning II
- Palindrome Partitioning II
- 【leetcode】Palindrome Partitioning II
- Palindrome Partitioning II
- leetcode - Palindrome Partitioning II
- Palindrome Partitioning II
- Palindrome Partitioning II
- [LeetCode]Palindrome Partitioning II
- [Leetcode]Palindrome Partitioning II
- [leetcode]Palindrome Partitioning II
- Palindrome Partitioning II
- leetcode Palindrome Partitioning II
- Palindrome Partitioning II
- LetCode:Palindrome Partitioning II
- LeetCode-Palindrome Partitioning II
- [leetcode] Palindrome Partitioning II
- ANT build.xml文件详解
- style,kind和type
- IOS中的几中观察监听模式
- 菜鸟SQL注入详解
- 注意Hibernate4在开发当中的一些改变
- Palindrome Partitioning II
- sql注入原理和过程
- Sphinx+Scws 搭建千万级准实时搜索&应用场景详解
- 【xinfanqie】分享:路由器死机如何处理?
- 让C程序更高效的10种方法
- SQL注入原理,值得一看!
- .NET 项目中引用的DLL 版本不一致的问题
- AIX 操作系统下常用命令
- Logcat过滤及常见用法整理