Description

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.

Analysis

The first solution is a one which is almost the same with the standard solution to Matrix Multiplication. We use to record the minimum number of cuts between and , which can be calculated by

.

However, there are some redundant and unnecessary operations involved. Instead of computing for all possible pairs , can we find a solution that reduces the amount of computation? The answer is yes.

Let us define a new variable . In Solution 2, we only compute , i.e. .

For the substring , we define to be the set of indices less than

then

  • , if is NOT a palindrome
  • , if is a palindrome

Below is the pseudo code of the algorithm. In this algorithm, can be precomputed in time. Therefore, the total time complexity is .

 1 //pseudo code in mixed C++-Python style
 2 	for (int i = 0; i < n; ++ i)
 3 		if (is_palindrome[0][i])
 4 			minCut[i] = 0
 5 		else
 6 			minCut[i] = MAX_INT
 7 			for (int j = 0; j < i; ++ j)
 8 				if (is_palindrome[j+1][i])
 9 					minCut[i] = min(minCut[i], minCut[j] + 1);
10 	return minCut[n-1]

Solution

solution

If you run this code in leetcode OJ, you will get runtime error, as there is a test case where the length of the string is more than 1400. Allocating a 2-D int array with elements leads to runtime error.

You can replace int num[n][n] with unsigned char num[n][n], but it is still a nasty solution and will get you a TLE.

 1 class Solution {
 2 public:
 3     int minCut(string s) {
 4         int n  = s.size();
 5         if (!n) return 0;
 6         int num[n][n];
 7         for (int i = 0; i < n; ++ i)
 8             memset(num[i], 0, sizeof(int) * n);
 9         
10         for (int i = 0; i < n - 1; ++ i)
11             num[i][i+1] = (s[i] != s[i+1]);
12         
13         for (int len = 3; len <= n; ++ len){    
14             for (int start = 0; start < n - len + 1; ++ start){
15                 int end = start + len - 1;
16                 if (num[start+1][end-1] == 0 && s[start] == s[end])
17                     num[start][end] = 0;
18                 else{
19                     num[start][end] = 2100000000;
20                     for (int k = start; k < end; ++ k)
21                         num[start][end] = min(num[start][k]+num[k+1][end]+1, num[start][end]);
22                 }
23             }
24         }
25         return num[0][n-1];
26     }
27 };

solution

 1 class Solution{
 2 public:
 3 	int minCut(string s) {
 4 		int n = s.size();
 5 		if (!n) return 0;
 6 		
 7 		// palindrome judgement
 8 		bool isPal[n][n];
 9 		for (int i = 0; i < n - 1; ++ i)
10 			isPal[i][i] = true, isPal[i][i+1] = (s[i] == s[i+1]);		
11 		isPal[n-1][n-1] = true;			
12 
13 		for (int len = 3; len <= n; ++ len)
14 			for (int start = 0; start < n - len + 1; ++ start){
15 				int end = start + len - 1;
16 				isPal[start][end] = (s[start] == s[end]) && isPal[start+1][end-1];
17 			}			
18 		
19 		//calculate minimum number of cut
20 		int minCutArray[n];
21 		minCutArray[0] = 0;
22 		for (int i = 1; i < n; ++ i){
23 		    if (isPal[0][i]){
24 		        minCutArray[i] = 0;
25 		        continue;
26 		    }
27 			minCutArray[i] = 2100000000;
28 			for (int j = 0; j < i; ++ j ){
29 				if (isPal[j+1][i])
30 					minCutArray[i] = min(minCutArray[i], minCutArray[j] + 1);
31 			}
32 		}
33 		return minCutArray[n-1];
34 	} 
35 };

Comments