我有以下问题:
给定一个字符串s,分区s使得每个子字符串 分区是回文。
返回s的回文分区所需的最小切割。
我得到了正确的解决方案,但我错过了优化步骤,尤其是DP中需要的记忆步骤。
public int minCut(String a) {
if (isValidPal(a)) {
return 0;
}
return minCut(a, 0, 0);
}
int min = Integer.MAX_VALUE;
private int minCut(String a, int cut, int index) {
// too many cuts already
if(cut >= min) return min;
// out of index
if (index >= a.length()) {
// what is left is a pal
if (isValidPal(a)) {
min = Math.min(min, cut);
return cut;
}
return Integer.MAX_VALUE;
}
int newCut = Integer.MAX_VALUE;
if (isValidPal(a.substring(0, index + 1))) {
// then cut
newCut = minCut(a.substring(index + 1), cut + 1, 0);
}
// continue either way
newCut = Math.min(minCut(a, cut, index + 1), newCut);
return newCut;
}
HashMap<String, Boolean> memo = new HashMap<>();
private boolean isValidPal(String s) {
if(memo.containsKey(s)) {
return memo.get(s);
}
boolean result = true;
for (int i = 0; i < s.length() / 2; i++) {
if (s.charAt(i) != s.charAt(s.length() - i - 1)) {
result = false;
break;
}
}
memo.put(s, result);
return result;
}
答案 0 :(得分:0)
尝试添加备忘录来存储计算结果,假设您的算法正确,这应该进行优化
Map<String, Integer> dp = new HashMap<>();
private int minCut(String a, int cut, int index) {
// too many cuts already
if(cut >= min) return min;
String key = cut + " " + index;
//test if the memo contains the answer if yes return it
if(dp.containsKey(key)) return dp.get(key);
// out of index
if (index >= a.length()) {
// what is left is a pal
if (isValidPal(a)) {
min = Math.min(min, cut);
return cut;
}
return Integer.MAX_VALUE;
}
int newCut = Integer.MAX_VALUE;
if (isValidPal(a.substring(0, index + 1))) {
// then cut
newCut = minCut(a.substring(index + 1), cut + 1, 0);
}
// continue either way
newCut = Math.min(minCut(a, cut, index + 1), newCut);
//put the computed answer in the memo table
dp.put(key, newCut);
return newCut;
}
答案 1 :(得分:0)
我很抱歉,但我的回答是基于你的代码是正确的,这是一个使用memoization进行min indindrom分区的工作示例
import java.util.*;
class Main {
static HashMap<String, Integer> memo = new HashMap<>();
static String s;
static int f(int i, int j){
if(i == j) return 0;
if(isPalindrom(s.substring(i, j))) return 0;
String key = i + " " + j;
if(memo.containsKey(key)) return memo.get(key);
int ans = 999999;
for(int k = i; k < j; k++){
ans = Math.min(ans, f(i, k) + f(k + 1, j) + 1);
}
memo.put(key, ans);
return ans;
}
static boolean isPalindrom(String s){
return s.equals(new StringBuilder(s).reverse().toString());
}
public static void main(String[] args) {
s = "aaka";
System.out.println(f(0, s.length()));
}
}