LeetCode - 解题笔记 - 131 - Palindrome Partitioning

Solution 1

整个题就是之前既有的DFS的模式题,深度枚举所有的拆分方案,并要求所有的子串都满足回文要求,可以通过提前判断每个字符串是否回文向下搜索进行剪枝。

官方题解中,结合了 0005. Longest Palindromic Substring 的动态规划思路进一步简化了判断流程。

  • 时间复杂度: O ( N × 2 N ) O(N \times 2^N) O(N×2N),其中 N N N是输入字符串的长度,子串生成和回文串判断需要线性复杂度,DFS最坏情况下需要全枚举。
  • 空间复杂度: O ( N ) O(N) O(N),其中 N N N是输入字符串的长度,递归的函数占用,最坏情况下每个字符占一次递归调用
class Solution {
public:
    vector<vector<string>> partition(string s) {
        vector<vector<string>> ans;
        vector<string> temp;
        dfs(ans, temp, s, 0);
        
        return ans;
    }
    
private:
    void dfs(vector<vector<string>> & ans, vector<string> & temp, string & s, int start) {
        if (start >= s.size()) {
            ans.push_back(temp);
            return;
        }
        
        for (int i = start; i < s.size(); i++) {
            if (isPalindrome(s, start, i)) {
                // cout << start << " " << i << " " << s << " " << s.substr(start, i - start + 1) << endl;
                temp.push_back(s.substr(start, i - start + 1));
                dfs(ans, temp, s, i + 1);
                temp.pop_back();
            }
            
        }
    }
    
    bool isPalindrome(string & s, int start, int i) {
        int head = start, tail = i;
        // cout << head << " " << tail << endl;
        while (head < tail) {
            if (s[head] != s[tail]) {
                return false;
            }
            
            head++;
            tail--;
        }
        
        return true;
    }
};

Solution 2

根据官方题解,利用 0005. Longest Palindromic Substring 的思路,保存所有的小长度字符串的状态,只需要根据边界状态和内部子串状态进行回文串判断。

  • 时间复杂度: O ( N × 2 N ) O(N \times 2^N) O(N×2N),其中 N N N是输入字符串的长度,子串生成需要线性复杂度,DFS最坏情况下需要全枚举。
  • 空间复杂度: O ( N 2 ) O(N^2) O(N2),其中 N N N是输入字符串的长度,函数调用需要线性复杂度,此外还有一个dp数组
class Solution {
public:
    vector<vector<string>> partition(string s) {
        vector<vector<string>> ans;
        vector<string> temp;
        vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
        // dfs(ans, temp, s, 0);
        dfs2(ans, temp, s, 0, dp);
        
        return ans;
    }
    
private:
    void dfs2(vector<vector<string>> & ans, vector<string> & temp, string & s, int start, vector<vector<bool>> & dp) {
        if (start >= s.size()) {
            ans.push_back(temp);
            return;
        }
        
        for (int i = start; i < s.size(); i++) {
            // 实际上就是先迭代尾边界
            if (s[start] == s[i] && (i - start <= 2 || dp[start + 1][i - 1])) {
                // cout << start << " " << i << " " << s << " " << s.substr(start, i - start + 1) << endl;
                dp[start][i] = true;
                temp.push_back(s.substr(start, i - start + 1));
                dfs2(ans, temp, s, i + 1, dp);
                temp.pop_back();
            }
            
        }
    }
};

Solution 3

Solution 1的Python实现

class Solution:
    def partition(self, s: str) -> List[List[str]]:
        
        def dfs(start: int) -> None:
            nonlocal ans
            nonlocal temp
            
            if start >= len(s):
                ans.append(copy.deepcopy(temp))
                return
            
            for i in range (start, len(s)):
                if isPalindrome(start, i):
                    # print("DO", start, i, s[start: i + 1])
                    temp.append(s[start: i + 1])
                    dfs(i + 1)
                    temp.pop()
                    
        def isPalindrome(start, i):
            # print("TEST", start, i, s[start: i + 1])
            head, tail = start, i
            while head < tail:
                if s[head] != s[tail]: return False
                
                head += 1
                tail -= 1
                
            return True
        
        ans = list()
        temp = list()
        
        dfs(0)
        
        return ans

Solution 4

Solution 2的Python实现

class Solution:
    def partition(self, s: str) -> List[List[str]]:
        def dfs2(start: int) -> None:
            nonlocal ans
            nonlocal temp
            nonlocal dp
            
            if start >= len(s):
                ans.append(copy.deepcopy(temp))
                return
            
            for i in range (start, len(s)):
                if s[start] == s[i] and (i - start <= 2 or dp[start + 1][i - 1]):
                    # print("DO", start, i, s[start: i + 1])
                    dp[start][i] = True
                    
                    temp.append(s[start: i + 1])
                    dfs2(i + 1)
                    temp.pop()
        
        ans = list()
        temp = list()
        dp = [[False] * len(s) for i in range(len(s))]
        
        # dfs(0)
        dfs2(0)
        
        return ans
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值