【LeetCode】palindrome-partitioning i&ii

题干

palindrome-partitioning i

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"]
  ]

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”,
Return1since the palindrome partitioning[“aa”,”b”]could be produced using 1 cut.

两个回文字符串的题,第一个要把字串都是回文的情况都存储下来,第二个是求得到字串都是回文需要对原字符串分割多少次。

解题思路

第一个题

对字符串进行遍历,每当找到一个回文的子串之后,继续找剩下的子串中的会问子串,利用递归直到找完整个字符串即可。动态规划也可解。

第二个题

运用动态规划的想法,主要步骤分为3步。

1.子串substr(0,i+1)的最小回文分割为dp[i],并且初始化,如果substr(0,i+1) 为回文子串,那么dp[i]=0,即不需要分割,否则为i,即分割i 次

  1. 任意大于1的i,子串substr(j,i+1),即遍历i之前所有子串,是回文子串,dp[i]=min(dp[i],dp[j-1]+1),即再分割一次。

  2. 如果子串substr(j,i+1)不是回文,dp[i]=min(dp[i],dp[j-1]+i-j+1)

    上述构成写成代码即可。

参考代码

问题一:

class Solution {
public:
    vector<vector<string>>res;//结果的每组子串存储
    vector<string> tmp;//当前子串
    bool isPalindrome (string s)//是否为回文的判断
    {
        if (s.size()<=0) return false;
        int start=0,end=s.size()-1;
        while(start<=end)
        {
            if(s[start]==s[end])
            {
                start++;
                end--;
            }
            else return false;
        }
        return true;
    }
    void dfs(string s,int pos)//子串遍历
    {
        if (pos>=s.size())//递归退出条件,原字符串全部遍历之后退出递归
        {
            res.push_back(tmp);
            return;
        }

        for(int i=0;i<=s.size()-pos;i++)
        {
            if (isPalindrome(s.substr(pos,i)))
            {
                tmp.push_back(s.substr(pos,i));//将回文子串存到结果中
                dfs(s,pos+i);//从当前位置继续后面的遍历
                tmp.pop_back();
            }
        }
    }
    vector<vector<string>> partition(string s)
    {
        dfs(s,0);
        return res;
    }
};

问题二:

class Solution {
public:
    bool isPalindrome (string s)//回文判断
    {
        if (s.size()<=0) return false;
        int start=0,end=s.size()-1;
        while(start<=end)
        {
            if(s[start]==s[end])
            {
                start++;
                end--;
            }
            else return false;
        }
        return true;
    }
    int minCut(string s)
    {
        int *dp=new int [s.length()];
        int min;
        for(int i=0;i<s.length();i++)
        {
            dp[i]=(isPalindrome(s.substr(0,i+1)))?0:i;//步骤1:初始化dp[i]
            if (dp[i]==0)//当dp[i]为0的时候必为min,故直接下一次循环
                continue;
            for(int j=1;j<=i;j++)
            {
                if (isPalindrome(s.substr(j,i-j+1)))//步骤2
                    dp[i]=(dp[i]<dp[j-1]+1)?dp[i]:dp[j-1]+1;
                else
                    dp[i]=(dp[i]<dp[j-1]+i-j+1)?dp[i]:dp[j-1]+i-j+1;//步骤3
            }

        }
        return dp[s.length()-1];//返回dp最后的结果
    }
};

方法讨论

两个题都可以用动态规划解决,字符串子串的这种问题主要用类似于深度遍历的方法,每次从当前位置向后遍历,适合用递归。

易错点

递归跳出条件

递归跳出是遍历结束之后进行跳出。

边界条件

1.回文判断的时候循环结束条件是要在前后两个指针顺序start<=end来结束,<或者=单独条件都不可以。

2.第2题中的s.substr(j,i-j+1)回文的判断对于子串长度为i-j+1。这个容易错误。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章