第五题,题意大概是这样的
输入
ababa
4
1 5
2 5
1 4
2 4
输出
1
2
2
1
解释:1 5表示子串为ababa,此时本就为回文,所以最少由一个回文串构成,2 5表示子串为baba,此时可由bab+a构成,也可由b+aba构成,所以输出为2
由于昨天在这道题上浪费了快50min,且未得分,心有不甘,感觉前半部分思路正确,但是后面计算最少组成的时候就脑袋宕机了,故在LeetCode上找了一个类似的题,进行解答,最后通过,便写下该博客。题为:分割回文串 II,给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串,返回符合要求的最少分割次数。所以此题与笔试题是差不多的,在笔试题的返回答案上减1即为该lc题的答案
思路为
import java.util.Arrays;
public class CycleString {
public static void main(String[] args) {
String s = "ababaccc";
int len = s.length();
boolean[][] dp = new boolean[len][len];
for(int i = len - 1;i >= 0;i--){
dp[i][i] = true;
for (int j = i+1; j < len ; j++) {
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = i == j - 1 || dp[i+1][j-1];
}
}
}
for (boolean[] booleans : dp) {
System.out.println(Arrays.toString(booleans));
}
int[][] res = new int[len][len];
for (int i = len - 1; i >= 0 ; i--) {
for (int j = i; j < len; j++) {
res[i][j] = len;
if(dp[i][j]){
res[i][j] = 1;
}else{
for (int k = i+1; k <=j ; k++) {
res[i][j] = Math.min(res[i][j],res[i][k-1]+res[k][j]);
}
}
}
}
for (int[] re : res) {
System.out.println(Arrays.toString(re));
}
}
}
上述代码中打印结果如下
[true, false, true, false, true, false, false, false]
[false, true, false, true, false, false, false, false]
[false, false, true, false, true, false, false, false]
[false, false, false, true, false, false, false, false]
[false, false, false, false, true, false, false, false]
[false, false, false, false, false, true, true, true]
[false, false, false, false, false, false, true, true]
[false, false, false, false, false, false, false, true]
[1, 2, 1, 2, 1, 2, 2, 2]
[0, 1, 2, 1, 2, 3, 3, 3]
[0, 0, 1, 2, 1, 2, 2, 2]
[0, 0, 0, 1, 2, 3, 3, 3]
[0, 0, 0, 0, 1, 2, 2, 2]
[0, 0, 0, 0, 0, 1, 1, 1]
[0, 0, 0, 0, 0, 0, 1, 1]
[0, 0, 0, 0, 0, 0, 0, 1]
emmm,一顿操作猛如虎,查询通过双百五,至少过了,而且这个用在笔试题上,应该会有效点吧,毕竟是在一个字符串上返回其多个子串最少由多少个回文串构成。复杂度确实高,但是胜在简单易懂,慢慢来吧。
import java.util.Scanner;
public class CycleString {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
int n = in.nextInt();
int[][] input = new int[n][2];
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
input[i][j] = in.nextInt() - 1;
}
}
in.close();
int len = s.length();
boolean[][] dp = new boolean[len][len];
for(int i = len - 1;i >= 0;i--){
dp[i][i] = true;
for (int j = i+1; j < len ; j++) {
if(s.charAt(i) == s.charAt(j)){
dp[i][j] = i == j - 1 || dp[i+1][j-1];
}
}
}
int[][] res = new int[len][len];
for (int i = len - 1; i >= 0 ; i--) {
for (int j = i; j < len; j++) {
res[i][j] = len;
if(dp[i][j]){
res[i][j] = 1;
}else{
for (int k = i+1; k <=j ; k++) {
res[i][j] = Math.min(res[i][j],res[i][k-1]+res[k][j]);
}
}
}
}
for (int[] ints : input) {
System.out.println(res[ints[0]][ints[1]]);
}
}
}
哎,笔试的时候就是这个思路,但是求res的时候,为了追求小的时间复杂度,陷入怪圈,没有使用代码中的for k,导致没拿分,做题还是要保持冷静。