参考: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的更多相关文章

  1. [LeetCode] Palindrome Partitioning II 解题笔记

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

  2. LeetCode: Palindrome Partitioning II 解题报告

    Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...

  3. [LeetCode] Palindrome Partitioning II 拆分回文串之二

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

  4. [leetcode]Palindrome Partitioning II @ Python

    原题地址:https://oj.leetcode.com/problems/palindrome-partitioning-ii/ 题意: Given a string s, partition s  ...

  5. LeetCode:Palindrome Partitioning,Palindrome Partitioning II

    LeetCode:Palindrome Partitioning 题目如下:(把一个字符串划分成几个回文子串,枚举所有可能的划分) Given a string s, partition s such ...

  6. leetcode@ [131/132] Palindrome Partitioning & Palindrome Partitioning II

    https://leetcode.com/problems/palindrome-partitioning/ Given a string s, partition s such that every ...

  7. 【leetcode】Palindrome Partitioning II

    Palindrome Partitioning II Given a string s, partition s such that every substring of the partition ...

  8. leetcode 131. Palindrome Partitioning 、132. Palindrome Partitioning II

    131. Palindrome Partitioning substr使用的是坐标值,不使用.begin()..end()这种迭代器 使用dfs,类似于subsets的题,每次判断要不要加入这个数 s ...

  9. 【LeetCode】132. Palindrome Partitioning II

    Palindrome Partitioning II  Given a string s, partition s such that every substring of the partition ...

随机推荐

  1. Indesign中GREP的应用

    1.查找m2,m3中的2或3:代码:(?<=m|M)(2|3)(?!\d)(查找这个可以统一改成上标) 2.删除段首空格:代码:^\s+(?=\w{2,}) 3.删除尾随空白:代码:\s+$ 4 ...

  2. 【UWP】解析GB2312、GBK编码网页乱码问题

    在WebHttpRequest请求网页后,获取到的中文是乱码,类似这样: <title>˹ŵ��Ϸ���������� - ��̳������ -  ˹ŵ��Ϸ����</title ...

  3. mysql 主主复制搭建用的命令

    # mysql 容器的启动docker run -d -p 3306:3306 -v /database_files/products/data:/var/lib/mysql -v /database ...

  4. JS这些代码你都不会,你还有什么好说的!!!

    都说自己工资低的,先看看这些代码你能写出来不?这些都不会,你还嫌工资?

  5. 2012Chhengdu K - Yet Another Multiple Problem

    K - Yet Another Multiple Problem Time Limit:20000MS     Memory Limit:65536KB     64bit IO Format:%I6 ...

  6. 使用ICSharpCode.SharpZipLib.Zip类库解压zip文件的方法

    public static bool ZipExtractFile(string zipFilePath,string targetPath) { FastZip fastZip = new Fast ...

  7. Apache SolrCloud安装

    1.介绍  SolrCloud通过ZooKeeper集群来进行协调,使一个索引进行分片,各个分片可以分布在不同的物理节点上,多个物理分片组成一个完成的索引Collection.SolrCloud自动支 ...

  8. inline-block和float

    Inline-block: 1.使块元素在一行显示 2.使内联支持宽高 3.换行被解析 4.不设置宽度,宽度由内容撑开 5.在IE6/7下不支持块标签 Float: 1.使块元素在一行显示 2.使内联 ...

  9. appium 九宫格解锁招商银行手机客户端app

    之前研究了一段时间的appium for native app 相应的总结如下:                                            appium测试环境搭建 :ht ...

  10. Swift 定义函数 参数 返回值

    定义多参数函数 - 用func声明函数  func name(parameters) -> return type { function body } func halfOpenRangeLen ...