zoukankan      html  css  js  c++  java
  • leetcode-Palindrome Partitioning II

    Palindrome Partitioning II

     Total Accepted: 11791 Total Submissions: 66110

    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.

    Have you been asked this question in an interview?

     


    这道题是Palindrome Partitioning的变形,要求求出最小的分割使得全部分割后的子串都是回文串。


    能够在Palindrome Partitioning的基础上改动。在找到可行解时。更新最优解。

    class Solution {
    public:
        int minCut(string s) {
            ans = INT_MAX;
            findMinCut(s, 0, 0);
            return ans;
        }
    private:
        int ans;
        
        void findMinCut(const string &s, int k, int currCut) {
            string substr;
            for (int i=k; i<s.size(); ++i) {
                if (isPalindrome(s, k, i)) {
                    if (i+1 == s.size()) {
                        if (currCut+1 < ans) {
                            ans = currCut+1;
                        }
                    } else {
                        findMinCut(s, i+1, currCut+1);
                    }
                }
            }
        }
        
        bool isPalindrome(const string &s, int b, int e) {
            int i=b, j=e;
            while (i<j) {
                if (s[i] != s[j])
                    return false;
                ++i;
                --j;
            }
            return true;
        }
    };

    假设添加记忆化搜索+剪枝,还是会TLE。超时的case是一大串"aaaa...aa"的情况。

    class Solution {
    public:
        int minCut(string s) {
            minCutNum = INT_MAX;
            vector<string> paths;
            find(s, 0, paths);
            return minCutNum;
        }
    private:
        int minCutNum;
        map<int, int> minCutsMap;
        void find(const string& s, int ind, vector<string>& paths)
        {
            for (int i = ind; i < s.size(); ++i) {
                if (isPalindrome(s, ind, i)) {
                    if (paths.size() > minCutNum)
                        continue;
                    if (minCutsMap.find(i+1) != minCutsMap.end()) {
                        if (paths.size() + minCutsMap.size() - 1 < minCutNum) {
                            minCutNum = paths.size() + minCutsMap.size() - 1;
                        }
                        continue;
                    }
                    paths.push_back(s.substr(ind, i - ind + 1));
                    if (i + 1 == s.size()) {
                        if (minCutNum > paths.size() - 1) {
                            minCutNum = paths.size() - 1;
                        }
                        paths.pop_back();
                        continue;
                    }
                    int num = paths.size();
                    minCutsMap[i + 1] = INT_MAX;
                    find(s, i + 1, paths);
                    if (minCutsMap[i + 1] > paths.size() - num) {
                        minCutsMap[i + 1] = paths.size() - num;
                    }
                    if (minCutNum == 0)
                        return;
                    paths.pop_back();
                }
            }
        }
        bool isPalindrome(const string& str, int begin, int end)
        {
            while (begin < end) {
                if (str[begin] != str[end])
                    return false;
                ++begin; --end;
            }
            return true;
        }
    };

    最后网上參考了别人的DP,自己写了下,最终看到Accepted

    初始化isPalindrome的方法也是用了DP的方法,跟计算矩阵连乘最小操作数类似。

    如果字符串为str。长度为n,计算最小分割数的状态转移方程为:dp[i] = min{dp[j]+1,dp[i]}(j=i+1...n-1), 当中dp[i]为str[i]...str[n-1]的最小分割数。在做DP题时,要考虑清楚怎么存状态,以及状态是怎样转移的。DP的长处就是可以依据曾经的选择来做出当下最优的选择,像贪心算法就不能,仅仅有曾经局部最优的状态。

    class Solution {
    public:
        int minCut(string s) {
            int len = s.size();
            bool **isPalindrome = new bool*[len];
            for (int i = 0; i < len; ++i) {
                isPalindrome[i] = new bool[len];
            }
            initIsPalindrome(isPalindrome, s);
            
            int *dp = new int[len]; // dp[i] stores minimum cuts for s[i]...s[len-1]
            for (int i = len - 1; i >= 0; --i) {
                if (isPalindrome[i][len - 1]) {
                    dp[i] = 0;
                    continue;
                }
                dp[i] = INT_MAX;
                for (int j = i + 1; j < len; ++j) {
                    if (isPalindrome[i][j - 1]) {
                        if (dp[j] + 1 < dp[i]) {
                            dp[i] = dp[j] + 1;
                        }
                    }
                }
            }
            int ret = dp[0];
            for (int i = 0; i < len; ++i)
                delete []isPalindrome[i];
            delete []isPalindrome;
            delete dp;
            return ret;
        }
    private:
        void initIsPalindrome(bool ** isPalindrome, const string& s) {
            int len = s.length();
            for (int L = 1; L <= len; ++L) { // L is the length of substring, from 1 to len
                for (int i = 0; i < len - L + 1; ++i) { // i is the starting index
                    int j = i + L - 1; // j is the ending index
                    if (L == 1) {
                        isPalindrome[i][j] = true;
                    } else if (L == 2) {
                        isPalindrome[i][j] = s[i] == s[j];
                    } else {
                        isPalindrome[i][j] = (s[i] == s[j]) && isPalindrome[i + 1][j - 1];
                    }
                }
            }
        }
    };
       




  • 相关阅读:
    Swift 协议
    Objective C 链式调用
    objective-c 关键字和概念
    如何在Objective-C中实现链式语法?
    _视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear等的区别及用途
    Swift静态方法
    Swift静态属性
    objective-c 中代码块(blocks)
    OS笔记047代理传值和block传值
    Objective-C官方文档翻译 Block
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/6949903.html
Copyright © 2011-2022 走看看