Given A string s, partition s such that every substring of the partition are 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.
Problem Solving Ideas:
This is a more difficult topic, I also refer to the idea of netizens, I write a method, but still time out. Let's talk about the process of thinking.
This problem is similar to the previous question, but is not to ask all the palindrome partition solution, but to find the best solution in so many solutions, that is, the smallest cut quantity. Generally, the optimal solution is to use dynamic programming, which is a big idea. Because if like palindrome partitioning, with Dfs backtracking, find out all the solutions, then return the smallest, it is certainly possible. However, there will be a time-out, because there are a lot of repeated judgments, after each backtracking, we have to judge where the following position is likely to be partition. Therefore, you can first use the method of Ispalindrome, with O (n^2) time to the original string to construct a record is palindrome dictionary, dict[i][j] = = 1 means s.substring (i, J) is Palindrome, So here length is set to S.length () + 1.
The second step is to define the DP state of interest, Dp[i] is the minimum cut quantity for s.substring (0, I). So the size of the DP here must also be s.length () + 1. Let's look at the recursive relationship of the sub state. Given a substring s[0...i], loop to judge S[0...j-1] and s[j...i-1], if the latter is a palindrome, then the total cut quantity is in the substring s[0...j-1] cut number +1, that is dp[j] + 1. So, Dp[i] is the optimal solution (minimum) within the loop.
So there is the state transition equation: dp[i] = min (dp[j] + 1) (s.substring (0, J) is palindrome).
The way that this state is converted, like a Word break that has been done before, is in a substring that ends with the current subscript, backtracking backwards, looking for possible solutions, or optimal solutions. Word break is looking for a possible solution, and here is the optimal solution. Then the optimal solution of the whole is recorded in the last position of DP. Similar to the Jump Game topic, there is also a concept of local optimality and overall optimality.
Public classSolution { Public intmincut (String s) {if(s = =NULL|| S.length () = = 0 | | S.length () = = 1) { return0; } int[] Dict =Getpalindromedict (s); int[] DP =New int[S.length () + 1]; for(inti = 0; i < dp.length; i++) {Dp[i]=-1; } dp[0] = 0; for(inti = 1; I < S.length () + 1; i++) { intMin =-1, temp = 1; for(intj = 0; J < I; J + +) { if(Dict[j][i] = = 1 && dp[j]! =-1) {Temp= Dp[j] + 1; Min= min = =-1?temp:Math.min (min, temp); }} Dp[i]=min; } returnDp[s.length ()]-1; } Public int[] getpalindromedict (String s) {int[] Dict =New int[S.length () + 1] [S.length () + 1]; for(inti = 0; I < s.length (); i++) { for(intj = i + 1; J < S.length () + 1; J + +) { if(Ispalindrome (S.substring (i, J))) {Dict[i][j]= 1; } } } returndict; } Public BooleanIspalindrome (String s) {if(s.length () = = 0) { return true; } intStart = 0, end = S.length ()-1; while(Start <end) { if(S.charat (start)! =S.charat (end)) { return false; } Start++; End--; } return true; }}
The result is still time-out, using DP or time-out, only to see Daniel's solution. Originally is Getpalindromedict method, also should use DP to do. Definition Dict[i][j] = = 1 Description s.substring (i, J + 1) is palindrome, then dict[i-1][j + 1] can be judged on the basis of dict[i][j], as long as S.charat (i-1) = = S.chara T (j + 1).
With this change, the time complexity of calculating dict becomes O (n^2). Looking back to see the above method, although the loop is also two layers, but the inner layer is called ispalindrome, and then added a layer of cycle, time complexity reached O (n^3).
Here the subscript of the dict is changed, is the s.substring (i, j + 1) instead of the s.substring (I, J), so the length requires only s.length ().
Public classSolution { Public intmincut (String s) {if(s = =NULL|| S.length () = = 0 | | S.length () = = 1) { return0; } int[] Dict =Getpalindromedict (s); int[] DP =New int[S.length () + 1]; for(inti = 0; i < dp.length; i++) {Dp[i]=-1; } dp[0] = 0; for(inti = 1; I < S.length () + 1; i++) { intMin =-1, temp = 1; for(intj = 0; J < I; J + +) { if(Dict[j][i-1] = = 1 && dp[j]! =-1) {Temp= Dp[j] + 1; Min= min = =-1?temp:Math.min (min, temp); }} Dp[i]=min; } returnDp[s.length ()]-1; } Private int[] getpalindromedict (String s) {int[] Dict =New int[S.length ()][s.length ()]; for(inti = 0; I < s.length (); i++) { for(intj = i; J >= 0; j--) { if(i = =j) {Dict[j][i]= 1; }Else if(I-j = = 1) { if(S.charat (i) = =S.charat (j)) {Dict[j][i]= 1; } }Else { if(S.charat (i) = = S.charat (j) && Dict[j + 1][i-1] = = 1) {Dict[j][i]= 1; } } } } returndict; }}
The result of the above code is AC.
Here's a little bit more optimized. Assigning a DP array initializer to 1 is unnecessary, because for any subscript i,dp[j] must be >0, here j<i. Because again, each character cut can also, so do not use-one to judge. Before the main is the brain show tease, the condition is judged as s[j...i] is palindrome, and S[0...J] can be palindrome partitioning. Nonsense, S[0...J] is bound to be palindrome partitioning Ah!
As a result, the following code is available.
Public classSolution { Public intmincut (String s) {if(s = =NULL|| S.length () = = 0 | | S.length () = = 1) { return0; } //Dict[i][j] = = 1,s.substring (i, J + 1) is palindrome int[] Dict =Getpalindromedict (s); //minimum cut quantity for dp[i],s.substring (0, I) + 1 int[] DP =New int[S.length () + 1]; dp[0] = 0; for(inti = 1; I < S.length () + 1; i++) { intMin =-1, temp = 1; for(intj = 0; J < I; J + +) { if(Dict[j][i-1] = = 1) {Temp= Dp[j] + 1; Min= min = =-1?temp:Math.min (min, temp); }} Dp[i]=min; } returnDp[s.length ()]-1; } Private int[] getpalindromedict (String s) {int[] Dict =New int[S.length ()][s.length ()]; for(inti = 0; I < s.length (); i++) { for(intj = i; J >= 0; j--) { if(i = =j) {Dict[j][i]= 1; }Else if(I-j = = 1) { if(S.charat (i) = =S.charat (j)) {Dict[j][i]= 1; } }Else { if(S.charat (i) = = S.charat (j) && Dict[j + 1][i-1] = = 1) {Dict[j][i]= 1; } } } } returndict; }}
In general, this problem was used two times DP. The two-dimensional DP difficulty mainly lies in the modeling of sub-state, and the search of state transition equation.
Here I summarized above, for each subscript I, to the loop to find 0<=j<=i, according to the state of the left and right two satin strings to write the state conversion equation. At the same time, it also maintains a current optimal and all-optimal solution.
Getpalindromedict This method is also a DP, and is a two-dimensional DP. With the result of the previous deposit, the solution can be extended to both sides, eliminating a heavy cycle. It should be said, and the above is very intuitive, but also more ingenious.
On the whole, still need to work hard, only by doing the problem to find the law.
Palindrome Partitioning II