Leetcode(132) 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.


分析如下:

从左到右扫描s一遍,每一步都有一个子串S1, 对S1进行所有可能的切割,从所有可能的切割中找寻最小mincut并且记录在一个数组中。

以 aab为例子来看看: 

第一步: 扫到S1 = a, 显然mincut = 0,

第二步, 扫到S1 = aa.

切割1: [aa] ,显然mincut = 0.

切割2:   [a] + [a], 显然mincut = 1.

上面的切割方式中取最小值,mincut = 0.

第三步, 扫到S1 = aab

切割1:    [aab] , 显然aab本身不是一个回文,因此不用更新mincut.

切割2: [a] + [ab] = 1+[ab] = 2;

切割3: [aa] + [b] = 1+[b] = 1;

真正在计算的时候,如何判断回文可以优化。如果采用上面一题的思路,那么每次进行回文的判断都会是O(N)的复杂度。为了优化,可以事先判断好了把信息存起来,放入一个2D数组中,这样用空间换了时间,接下来每次进行回文的判断都是O(1)的复杂度了。


我的代码:

class Solution {
private:
    int** palindrome_table = NULL;
public:
    void gen_table (int** &table, string &s) { //这里是int** &型,不是int**行,因为要将table分配空间后对应的新地址传回实参,不仅仅要修改table指向的内容。
        table = new int*[s.length()];
        for (int i = 0; i < s.length(); ++i) {
            table[i] = new int[s.length()];
            for (int j = 0; j < s.length(); ++j) {
                table[i][j] = 0;
            }
        }
        int left = 0, right = 0, i = 0;
        //把回文判断信息放入一个2D数组中。
        while (i < s.length()) {
            left = i;
            right = i;
            //以第i个字符为中心,向两边扩展找寻形式为X,Y,Z,i,Z,Y,X的回文。
            while(left>=0 && right <s.length() && s[left] == s[right]) {
                table[left][right] = 1;
                left--;
                right++;
                
            }
            left = i;
            right = i+1;
            //以第i个字符和第i+1个字符为中心,向两边扩展找寻形式为X,Y,Z,i,i+1,Z,Y,X的回文。
            while(left>=0 && right <s.length() && s[left] == s[right]) {
                table[left][right] = 1;
                left--;
                right++;
                
            }
            i++;
        }
        return;
    }
    bool isPalindrome (int i, int j) {
        return palindrome_table[i][j];
    }
    int minCut(string s) {
        if (s.length() <= 1)
            return 0;
        gen_table(palindrome_table, s);
        int* record = new int[s.length()];
        for (int k = 0; k < s.length();++k)
            record[k] = k;
        for (int i = 1; i < s.length(); ++i) {
            if (isPalindrome(0, i)) record[i] = 0;
            for (int j = 1; j <= i; ++j) {
                if(isPalindrome(j, i))
                    if(record[j - 1] + 1 < record[i] )
                        record[i] = record[j - 1] + 1;
                                //std::cout<<"i="<<i<<", j="<<j<<", substring=" <<s.substr(j, i - j + 1)<<", record[i]="<<record[i]<<", record[j]="<<record[j]<<std::endl;
            }
        }
        int result = record[s.length() - 1];
        delete record;
        for (int i =0; i < s.length(); ++i) {
            delete palindrome_table[i];
        }
        delete palindrome_table;
        return result;
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值