zoukankan      html  css  js  c++  java
  • Palindrome Partitioning II 解答

    Question

    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.

    Example:

    Input: "aab" Output: 1 Explanation: The palindrome partitioning ["aa","b"] could be produced using 1 cut.

    Solution

    第一个思路是和Palindrome Partitioning解答思路相似,先用二维DP得到palindrome结果,然后用DFS.

    时间复杂度O(N^2) 空间复杂度O(N^2)

     1 class Solution:
     2     def check(self, s: str) -> None:
     3         n = len(s)
     4         self.dp = [[False for i in range(n)] for j in range(n)]
     5         for i in range(n):
     6             self.dp[i][i] = True
     7         for i in range(n - 1):
     8             if s[i] == s[i + 1]:
     9                 self.dp[i][i + 1] = True
    10         for k in range(3, n + 1):
    11             for i in range(n - k + 1):
    12                 j = i + k - 1
    13                 if s[i] == s[j] and self.dp[i + 1][j - 1]:
    14                     self.dp[i][j] = True
    15     
    16     def dfs(self, s: str, start: int, record: List[str], result: List[int]) -> None:
    17         n = len(s)
    18         if start == n:
    19             cut_num = len(record) - 1
    20             result[0] = min(cut_num, result[0])
    21             return
    22         for end in range(start, n):
    23             if self.dp[start][end]:
    24                 record.append(s[start: end + 1])
    25                 self.dfs(s, end + 1, record, result)
    26                 record.pop()
    27     
    28     def minCut(self, s: str) -> int:
    29         self.check(s)
    30         result = [len(s) - 1]
    31         self.dfs(s, 0, [], result)
    32         return result[0]
    33         

    但是这个方法在大数据测试的时候超时了,这时候需要思考怎样可以减少时间。

    一个重要的方法是再次使用DP。用一维DP:cut[i]表示从0到i-1的min cut数量。

     1 class Solution:
     2     def check(self, s: str) -> None:
     3         n = len(s)
     4         self.dp = [[False for i in range(n)] for j in range(n)]
     5         # one or two chars
     6         for i in range(n - 1):
     7             self.dp[i][i] = True
     8             self.dp[i][i + 1] = True if s[i] == s[i + 1] else False
     9         self.dp[n - 1][n - 1] = True
    10         # more chars
    11         for k in range(3, n + 1):
    12             for i in range(n - k + 1):
    13                 j = i + k - 1
    14                 self.dp[i][j] = True if s[i] == s[j] and self.dp[i + 1][j - 1] else False
    15     
    16     def minCut(self, s: str) -> int:
    17         self.check(s)
    18         n = len(s)
    19         # cut[i] means minimal cut number for s[0:i-1]
    20         cut = [len(s) - 1] * (n + 1)
    21         # notice here we need to set cut[0] = -1 so that if self.dp[0][n-1] is true, there is no cut needed
    22         cut[0] = -1
    23         for i in range(1, n + 1):
    24             for j in range(i - 1, -1, -1):
    25                 if self.dp[j][i - 1]:
    26                     cut[i] = min(cut[i], cut[j] + 1)
    27         return cut[n]

    尽管时间空间复杂度不变,但是在计算最小切割数时我们通过DP减少了很多重复计算的时间。

  • 相关阅读:
    PreparedStatementUpdateTest.java
    JDBCUtils.java
    StringTest.java
    创建线程的方式四:使用线程池
    用递归实现解决斐波那契数列。
    反射的用处。Class对象的介绍,怎么通过反射创建实例和调用方法。
    基于jenkins+docker+git 持续化自动部署项目(详细版一));
    git常用命令,linus的神作之一。
    电话号码的字母组合。(每天一道,防止痴呆)
    编写一个函数来查找字符串数组中的最长公共前缀。(每天一道防止痴呆)
  • 原文地址:https://www.cnblogs.com/ireneyanglan/p/11478832.html
Copyright © 2011-2022 走看看