[leetcode]Palindrome Partitioning II

来源:互联网 发布:prototype.js 1.6手册 编辑:程序博客网 时间:2024/06/06 05:34

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.

解题思路:先求出所有可能的回文串一次动态规划,然后在此基础上二次用动态规划求出最小分割次数

比较类似矩阵连乘问题,但是O(n^3)的复杂度会导致超时。

解法一超时

class Solution {public:    //判断字符串s [b,e]是不是回文    bool isPalindrome(string &s, size_t b, size_t e){        while(b < e){            if(s[b] != s[e]) return false;            b++; e--;        }        return true;    }    int minCut(string s) {        size_t n = s.size();        vector<vector<bool> > vvi(n, vector<bool>(n, false));        //动态规划 vvi[i, j]表示从i到j是回文串 此处的时间复杂度O(n^3)所以超果        for(int i = 0; i < n; i++){             for(int j = i; j < n; j++){                vvi[i][j] = isPalindrome(s, i, j); //这里需要优化            }        }                vector<int> vi(n,  0);        //二次动态规划        for(int i = 1; i < n; i++){            if(vvi[0][i]){                continue; //如果是回文串直接跳过            }            int tmpn = n;            //找出以j为分割点的所有最小划分            for(int j = 0; j < i; j++){                if(vvi[j + 1][i]){                    tmpn = min(tmpn, vi[j] + 1); //如果vvi[j+1][i]是回文串                }else{//如果不是                    tmpn = min(tmpn, vi[j] + i - j);                }            }            vi[i] = tmpn;        }                return vi[n - 1];    }};
针对解法一中需要优化的地方,要对求回文串也使用动态规划的方法
dp[i][j]表示从i到j的字符,包括i,j是回文串,如图所示

dp[i][j] = true; if(s[i] == s[j] && j - i < 2)
dp[i][j] = true; if(s[i] == s[j] && dp[i + 1][j - 1])
第二个表达式是一种递归的定义,如果s[i] s[j]相等,那么s[i + 1] 至s[j - 1]如果是回文即dp[i + 1][j - 1]为真则dp[i+1][j-1]为真
而对于最小切分也是一种动态规划
v[i]表示从0到i的最小切分次数
v[i] = min(v[k] + 1/* 0<= k < i, s[k + 1]至s[i]是回文串*/, v[k] + i - k/*s[k+1] 至s[i]不是回文串*/)
class Solution {public:    int minCut(string s) {        size_t n = s.size();        vector<vector<bool> > vvi(n, vector<bool>(n, false));        //动态规划 vvi[i, j]表示从i到j是回文串        for(int i = n - 1; i >= 0; i--){            for(int j = i; j < n; j++){                if(s[i] == s[j] &&(j - i < 2 || vvi[i + 1][j - 1])){                    vvi[i][j] = true;                }            }        }        vector<int> vi(n,  0);        for(int i = 1; i < n; i++){ //动态规划找最小划分次数            if(vvi[0][i]){                continue; //如果是回文串直接跳过            }            int tmpn = n;            //找出以j为分割点的所有最小划分            for(int j = 0; j < i; j++){                if(vvi[j + 1][i]){                    tmpn = min(tmpn, vi[j] + 1); //如果vvi[j+1][i]是回文串                }else{//如果不是                    tmpn = min(tmpn, vi[j] + i - j);                }            }            vi[i] = tmpn;        }                return vi[n - 1];    }};


0 0