leetcode Palindrome Partitioning I II

每到周五就想放松么,还是写两个题解吧。今天写了几个问题,发现都是动态规划的问题。就说这两个吧。

题1:

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

Return all possible palindrome partitioning of s.

For example, given s = "aab",
Return

  [
    ["aa","b"],
    ["a","a","b"]
  ]

找出所有的回文子串,如果是判断一个串是否是回文串,我想大家都应该能想出来。一般的判断一个串是否为回文串,直接从两头往中间找就可以了。这题的要求是让我们把这个字符串的所有子串都判断一遍。显然枚举每个子串的时间复杂度是O(n*n)的,加上判断的,算法时间复杂度是O(n*n*n)。同时判断完成时,还需要让原来的串划分为不同的回文串。这是个回溯,或者说dfs,因为要回复原来的状态,所要要回溯。

其实这是一个典型的动态规划问题,写这个的动态规划写法有几种。可以考虑从右往左,也可以从左往右。我在这里就写一个根据步长的。首先定义一个bool数组dp[i][j],表示从i到j是否是一个回文串。

状态转移,当dp[i+1][j-1]==1 &&s[i]==s[j]   或者只有一个元素     那么dp[i][j]=1;

步长++,就可以求出所有子串的状态。

有了第一步基础。下面的问题就变成了,搜索问题。很明显是一个深搜,出口条件是找到字符串最后位置。注意下回溯就好了。

class Solution {
public:
    vector<vector<string>> ss;  
    bool dp[1500][1500];
    vector<vector<string>> partition(string s) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
    int n=s.size();
    if(s.size() == 0)  
            return vector<vector<string>>(); 
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
            dp[i][j]=false;
        dp[i][i]=true;
    }
    for(int k=1;k<n;k++)
    {
        for(int i=0;i<n-k;i++)
        {
            if(k==1 && s[i]==s[i+k])
                dp[i][i+k]=true;
            else
                if(dp[i+1][i+k-1] &&s[i]==s[i+k])
                dp[i][i+k]=true;
        }
    } 
    vector<string> tem;
   
    dfs(0,n,s,tem);
    return ss; 
    }
    void dfs(int j,int n,const string &str,vector<string> &cur)
    {
    if(j==n)
    {
        ss.push_back(cur);
        return ;
    }
    for(int k=j;k<n;k++)
    {
        if(dp[j][k])
        {
            string t(str.begin()+j,str.begin()+k+1);
            cur.push_back(t);
            dfs(k+1,n,str,cur);
            cur.pop_back();
        }
    }
    }
};


第二题,mark下  明天早上来写吧。。。。。教研室关门了。。。。。。。


 教研室发了好多电影票,大家都去看电影啦,,我对电影没有兴趣,,还是继续写完吧。。。。。


题目2:

在要求几次分割可以将一个串分割为回文串。其实就是求一个串最少能用几个回文串表示嘛。所以我们求最少能用几个回文串表示就可以了。

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,可以利用前面求得的最少回文串。

思想就是从左往右开始,j=1;j++。。定义一个f[n]保存从0到i位置,最少回文串,初始时,f[i]=i+1;

求回文串的dp;

for(int j=1;j<n;j++)
{
    for(int i=j;i>=0;i--)
    {
      if(s[i]==s[j] && (j-i<2||dp[i+1][j-1]))
      dp[i][j]=true;
    }
}
j 从左往右遍历,每次i--就可以求得0,j所有子串是否为回文串。。更新f状态也比较简单,当dp[i][j]==true的时候,我们需要更新我们的f,状态转移f[j]=min(f[i-1]+1,f[j]);


int minCut(string s) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
   int n=s.size();
    vector<vector<bool> > dp(n,vector<bool>(n,false));
    for(int i=0;i<n;i++)
        dp[i][i]=true;
    int f[n];
    for(int i=0;i<n;i++)
        f[i]=i+1;
    for(int j=1;j<n;j++)
    {
        for(int i=j;i>=0;i--)
        {
            if(s[i]==s[j]&&(j-i<2||dp[i+1][j-1]))
            {
                dp[i][j]=true;
                if(i==0)
                    f[j]=min(f[j],1);
                else
                    f[j]=min(f[j],f[i-1]+1);
            }
        }
    }
    return f[n-1]-1;
}


写的匆忙,如果有不对的地方请大家多多指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值