说明:问题描述来源leetcode:
题解1:
/**
* @author xin麒
* @date 2022/12/14
* 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
* 回文串 是正着读和反着读都一样的字符串。
* 示例 1:输入:s = "aab" 输出:[["a","a","b"],["aa","b"]]
* 示例 2:输入:s = "a" 输出:[["a"]]
* 提示:1 <= s.length <= 16 s 仅由小写英文字母组成
*/
public class Solution {
List<List<String>> result = new ArrayList<>();
List<String> path = new LinkedList<>();
String s;
public List<List<String>> partition(String s) {
this.s = s;
backTracking(0);
return result;
}
private void backTracking(int startIndex) {
if (startIndex == s.length()) result.add(new ArrayList<>(path));
for (int i = startIndex; i < s.length(); i++) {
String str = s.substring(startIndex, i + 1);
String strReverse = new StringBuilder(str).reverse().toString();
if (!str.equals(strReverse)){//
//ToDo
continue;
}
path.add(str);
backTracking(i + 1);
path.remove(path.size() - 1);
}
}
}
问思路就是一点一点扣出来的,随便做的,直接手写出回溯的每一步的变量变化过程,在模板的基础上修修改改,对于每一次的遍历对象都要对截取的字符串进行反转判断,如果是回文,那么加到path;如果不是,那么可能再截取长一些的字符串就可能是回文串了,于是continue;做出来花了多久
看吧,一个半小时,而且效率还是20ms,完蛋:
优化一下:
题解2
class Solution {
List<List<String>> result = new ArrayList<>();
List<String> path = new LinkedList<>();
String s;
public List<List<String>> partition(String s) {
this.s = s;
backTracking(0);
return result;
}
private void backTracking(int startIndex) {
if (startIndex == s.length()) result.add(new ArrayList<>(path));
for (int i = startIndex; i < s.length(); i++) {
String str = doString(startIndex,i + 1);
if (str == null) continue;
path.add(str);
backTracking(i + 1);
path.remove(path.size() - 1);
}
}
private String doString(int startIndex, int end) {
int laterIndex = end - 1;
for (int i = startIndex; i< end; i++) {
if (i >= laterIndex ) return s.substring(startIndex, end );
if (s.charAt(i) != s.charAt(laterIndex)) return null;
laterIndex--;
}
return null;
}
}
9ms,还是不行
说说为什么我这个可以优化,因为前一个是用了StringBuilder来反转并且来判断地,每一次都要生成一个StringBuilder,而且反转后又要生成一个String;而这个9ms的程序有时还不一定会每次都会生成一个String,繁琐地生成对象,内存开辟空间等操作以及反转的操作的开销蛮大的,因此比20ms的效率高基本就高在这里。也就是对数据处理的优化。
这个9ms的优化是在判断截取的字符串是否为回文串时做了处理,但是这个是一个一个地处理截取字符串,对于非回文串之间没有联系。
有一个错觉就是如果要更加优化,可能要用到滑动窗口法,可恶可恶啊,又要烧脑!
再优化一下局部的代码,比如doString函数可以这样子写,少一次if的判断,但是效率没怎么变:
private String doString(int startIndex, int end) {
int laterIndex = end - 1;
for (int i = startIndex; i<= laterIndex; i++) {
if (s.charAt(i) != s.charAt(laterIndex--)) return null;
}
return s.substring(startIndex, end );
}
可能是要滑动窗口才可以100%吧,
优化到现在已经过去了这么多时间,将全局变量设置为局部变量(放递归函数里)可能会优化些吧:
做完看了其他人的好像也是和我的思路差不多,可能我还没看到有滑动窗口吧,算了后面有时间再去研究了[摆烂]。