Leetcode: palindrome-partitioning && palindrome-partitioning-ii

palindrome-partitioning

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

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s ="aab",

Return1since the palindromepartitioning["aa","b"]could be produced using 1 cut.

思想:这个和寻路的思想基本一样,用深度搜索即可,在判定遍历后的字符串是回文字符串之后,再递归调用函数遍历剩余未遍历的字符串。主要是记得回溯恢复状态

代码:

vector<vector<string>> partition(string s) {
        vector<vector<string>> d2_tmp;
        vector<string> tmp;
        dfs(s,tmp,d2_tmp);
        return d2_tmp;
    }
    void dfs(string s,vector<string>& tmp, vector<vector<string>>& d2_tmp)
    {
        if(s.empty())
        {
            d2_tmp.push_back(tmp);
            return;
        }
        int len = s.size();
        for(int i=0; i!=len; i++)
        {
            if(Is_palindr(s.substr(0,i+1)))
            {
                tmp.push_back(s.substr(0,i+1));   //dfs的精髓在于需要回溯,这里的push_back再pop_back就是回溯
                dfs(s.substr(i+1,len-(i+1)),tmp,d2_tmp);
                tmp.pop_back();
            }
        }
    }
    bool Is_palindr(string s)
    {
        int len=s.size();
        for(int i=0,j=len-1; i<j; i++, j--)
        {
            if(s[i] != s[j])
                return false;
        }
        return true;
}

palindrome-partitioning-ii

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

Return the minimum cuts needed for a palindrome partitioning of s.

For example, given s ="aab",
Return1since the palindrome partitioning["aa","b"]could beproduced using 1 cut.

思路:什么求极值(最小切割,最大切割,总共最多多少种…)的算法一般来说,都和动态规划有关。因此用动态规划解决。初始状态是一个字符串它自身的字符所处的位置下标是多少,就会被切割多少次,也就是初始化状态为最大切割数。同时,对于0到i为回文的,切割数置为0(回文不用切割)。

for(int i=0; i!=len; i++)

        {

           dp[i] = i;

           if(Is_palindr(s.substr(0,i+1)))

               dp[i]=0;

        }

dp[i]表示从开始到i能被切割的最小次数。那么它和状态有关呢?假设有个字符串为“aabbaacc”。长度为8,假设遍历已经遍历到第5个字符(下标从0开始),也就是i=5。

a     a    b   b    a   a  c    c

    j           i

此时dp[i=5]的最小切割数和dp[j-1]以及j到i的字符串是否为回文有关,dp[j]表示开始到j的最小切割数,既然已经求dp[i]的最小切割数,那么dp[j]的最小切割数肯定已知。

这时,假设j到i这段区间的字符串为回文的话,那么最少只需切一次即可(当然若初始化的时候dp[i]=0,那么肯定是dp[i]=0),那么整体0到i的最小切割数为0到j-1的最小切割数dp[j-1]再加1。即dp[i]=dp[j-1]+1。

若不是回文,则dp[i]=dp[j-1]+i-j+1。即加上j到i的长度。这就是状态转移方程。j是由i开始从左往右遍历的。

最后比较并保存最小。

代码:

int minCut(string s) {
        int len = s.size();
        vector<int> dp(len);
        for(int i=0; i!=len; i++)
        {
            dp[i] = i;
            if(Is_palindr(s.substr(0,i+1)))
                dp[i]=0;
        }
        for(int i=1; i!=len; i++)
        {
            for(int j=i; j>0; j--)
            {
                if(Is_palindr(s.substr(j,i-j+1)))
                    dp[i] = min(dp[i],dp[j-1]+1);
                else
                    dp[i] = min(dp[i],dp[j-1]+i-j+1);
            }
        }
        return dp[len-1];
    }
    bool Is_palindr(string s)
    {
        int len=s.size();
        for(int i=0,j=len-1; i<j; i++, j--)
        {
            if(s[i] != s[j])
                return false;
        }
        return true;
    }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值