LeetCode算法面试题汇总
分割回文串
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
示例:
输入: "aab"
输出:
[
["aa","b"],
["a","a","b"]
]
这题用到了回溯法,之前学算法又学到,但是o(╥﹏╥)o,全忘了。一开始想,只要我吧所有的可能都给找出来一一判断是不是回文,但是从来没想过回溯(完全忘了),哎。
class Solution {
List<List<String>> stulist=new ArrayList<List<String>>();
List<String> listtemp= new ArrayList<String>();
public List<List<String>> partition(String s) {
if(s=="") return stulist;
int len=s.length();
dfs(s, len,0);
return stulist;
}
public void dfs(String str,int strlength,int beginIndex){
if(strlength==beginIndex) {
stulist.add(new ArrayList<>(listtemp));
return;
}
for(int endIndex=beginIndex;endIndex<strlength;endIndex++){
//我发现如果你把代码块放在if里面,它的运行时间就会很高,改了之后从10ms,到了2ms
if(!isPalindrome(str,beginIndex,endIndex)){
continue;
}
listtemp.add(str.substring(beginIndex,endIndex+1));
dfs(str,strlength,endIndex+1);
listtemp.remove(listtemp.size()-1);
}
}
public boolean isPalindrome(String str,int left,int right){
while (right>=left){
if(str.charAt(right--)!=str.charAt(left++)){
return false;
}
}
return true;
}
}
找了一个大佬的,感觉好复杂看不懂
class Solution {
public List<List<String>> partition(String s) {
List<List<String>> res = new ArrayList<>();
int len = s.length();
boolean[][] dp = new boolean[len][len];
for(int i = 0; i < len; i++){
prePro(s, i, i, dp);
prePro(s, i, i + 1, dp);
}
helper(res, new ArrayList<>(), s, 0, dp);
return res;
}
//进行预处理,利用中心扩展 将所有回文子串的位置存储到 dp 中
private void prePro(String s, int left , int right, boolean[][] dp){
while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
dp[left][right] = true;
left--;
right++;
}
}
private void helper(List<List<String>> res, List<String> list, String s, int index, boolean[][] dp){
if(index == s.length()){
res.add(new ArrayList<>(list));
return;
}
for(int i = index; i < s.length(); i++){
//利用预处理结果就不用再去判断该字符串是否是回文串
if(!dp[index][i]){
continue;
}
list.add(s.substring(index, i + 1));
helper(res, list, s, i + 1, dp);
list.remove(list.size() - 1);
}
}
}
后来我从新学了了一遍动态规划,发现我们的那个回溯法重复判断了很多东西,所以我又增加了一个数组来存储已经判断过的子串,这样就会减少调用isPalindrome()的次数,减少运行时间。但是这样所占用的内存就会变大,
List<List<String>> stulist=new ArrayList<List<String>>();
List<String> listtemp= new ArrayList<String>();
int[][] is;
public List<List<String>> partition(String s) {
is=new int[s.length()][s.length()];
if(s=="") return stulist;
int len=s.length();
dfs(s,len,0);
return stulist;
}
public void dfs(String str,int strlength,int beginIndex){
if(strlength==beginIndex) {
stulist.add(new ArrayList<>(listtemp));
return;
}
for(int endIndex=beginIndex;endIndex<strlength;endIndex++){
if(is[beginIndex][endIndex]==0){
if(!isPalindrome(str,beginIndex,endIndex))
continue;
}
else if(is[beginIndex][endIndex]==1){
continue;
}
listtemp.add(str.substring(beginIndex,endIndex+1));
dfs(str,strlength,endIndex+1);
listtemp.remove(listtemp.size()-1);
}
}
public boolean isPalindrome(String str,int left,int right){
int lefttemp=left;
int righttemp=right;
while (right>=left){
if(str.charAt(right--)!=str.charAt(left++)){
is[lefttemp][righttemp]=1;
return false;
}
}
is[lefttemp][righttemp]=2;
return true;
}