136. 分割回文串
描述
给定字符串 s, 需要将它分割成一些子串, 使得每个子串都是回文串.
返回所有可能的分割方案.
样例
样例 1:
输入: “a”
输出: [[“a”]]
解释: 字符串里只有一个字符, 也就只有一种分割方式 (就是它本身)
样例 2:
输入: “aab”
输出: [[“aa”, “b”], [“a”, “a”, “b”]]
解释: 有两种分割的方式.
1. 将 “aab” 分割成 “aa” 和 “b”, 它们都是回文的.
2. 将 “aab” 分割成 “a”, “a” 和 “b”, 它们全都是回文的.
dfs + 回溯法
public class Solution {
/*
* @param s: A string
* @return: A list of lists of string
*/
private List<List<String>> list;
private boolean[][] dp ;
public List<List<String>> partition(String s) {
int n = s.length();
list = new ArrayList<>();
dp = new boolean[n][n];
for (int i = n - 1; i >= 0; i--) {
for(int j = i; j < n; j++) {
dp[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i <= 2 || dp[i +1][j - 1]);
}
}
dfs(s, 0, new ArrayList<>());
return list;
}
public void dfs(String s, int curr, List<String> temp) {
if (s.length() == curr) {
list.add(new ArrayList<>(temp));// 新建数组 不然会到导致浅拷贝 数据联动
return;
}
for (int i = curr; i < s.length(); i++) {
if (dp[curr][i]) {
temp.add(s.substring(curr, i + 1));
dfs(s, i + 1, temp);
temp.remove(temp.size() - 1); // 回溯
}
}
}
}
108. 分割回文串 II
描述
给定字符串 s, 需要将它分割成一些子串, 使得每个子串都是回文串.
最少需要分割几次?
样例
样例 1:
输入: “a”
输出: 0
解释: “a” 本身就是回文串, 无需分割
样例 2:
输入: “aab”
输出: 1
解释: 将 “aab” 分割一次, 得到 “aa” 和 “b”, 它们都是回文串.
public class Solution {
/**
* @param s: A string
* @return: An integer
*/
public int minCut(String s) {
// write your code here
int n = s.length();
boolean[][] dp = new boolean[n][n];
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
dp[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i <= 2 || dp[i + 1][j - 1]);
}
}
int[] f = new int[n + 1];
f[0] = 0;
for (int i = 1; i <= n; i++) {
f[i] = Integer.MAX_VALUE;
for(int j = 0; j < i; j++) {
if (dp[j][i - 1]) {
f[i] = Math.min(f[j] + 1, f[i]);
}
}
}
return f[n] - 1; // 因为是划分次数要减一
}
200. 最长回文子串
描述
给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串。
样例
样例 1:
输入:“abcdzdcab”
输出:“cdzdc”
样例 2:
输入:“aba”
输出:“aba”
public class Solution {
/**
* @param s: input string
* @return: a string as the longest palindromic substring
*/
public String longestPalindrome(String s) {
// write your code here
int n = s.length();
int res = 0;
int l = 0;
int r = 0;
boolean[][] dp = new boolean[n][n];
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
dp[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i <= 2 || dp[i + 1][j - 1]);
if (dp[i][j]) {
if (res < s.substring(i, j + 1).length()) {
res = s.substring(i, j + 1).length();
l = i;
r =j;
}
}
}
}
return s.substring(l, r + 1);
}
}
678. 最短回文串
描述
给一个字符串 S, 你可以通过在前面添加字符将其转换为回文串.找到并返回用这种方式转换的最短回文串.
您在真实的面试中是否遇到过这个题?
样例
样例1
输入: “aacecaaa”
输出: “aaacecaaa”
解释:
在输入字符串前面添加一个’a’。
样例2
输入: “abcd”
输出: “dcbabcd”
只能过90%
从尾巴开始取出 字符串 如果剩下的是一个回文字符串 就将取出的字符串逆序拼接到头部
public class Solution {
/**
* @param str: String
* @return: String
*/
public String shortestPalindrome(String str) {
// Write your code here
int n = str.length();
boolean[][] dp = new boolean[n][n];
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
dp[i][j] = (str.charAt(i) == str.charAt(j)) && (j - i <= 2 || dp[i + 1][j - 1]);
}
}
String res = "";
for (int i = n - 1; i > 0; i--) {
if (dp[0][i]) {
res = new StringBuffer(str.substring(i + 1 , n)).reverse().toString() + str;
break;
}
}
if (res.length() == 0 && n != 0) {
res = new StringBuilder(str).reverse().toString() + str.substring(1, str.length());
}
return res;
}
}