leetcode练习
回溯的模板
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
77.组合
ArrayList相当于是一个动态数组,LinkedList相当于一个双指针,可以直接删除列表最后一个元素。
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
void backtracking(int n, int k, int startIndex){
if(path.size() == k){
result.add(new ArrayList<>(path));
return;
}
for(int i = startIndex; i <= n - (k - path.size()) + 1; i++){
path.add(i);
backtracking(n, k ,i + 1);
path.removeLast();
}
}
public List<List<Integer>> combine(int n, int k) {
backtracking(n, k, 1);
return result;
}
39.组合总和
每次递归的起始位置应该是上一次加入path的元素位置,以此保证没有重复结果。
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
void backtracking(int[] candidates, int target, int startIndex){
if(path.stream().mapToInt(Integer::intValue).sum() == target){
result.add(new ArrayList(path));
return;
}
for(int i = startIndex; i < candidates.length; i++){
if(candidates[i] > target - path.stream().mapToInt(Integer::intValue).sum()) continue;
path.add(candidates[i]);
backtracking(candidates, target ,i);
path.removeLast();
}
}
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtracking(candidates, target , 0);
return result;
}
131.分割回文串
List<List<String>> result = new ArrayList<>();
LinkedList<String> path = new LinkedList<>();
void backtracking(String s, int startIndex){
if(startIndex == s.length()){ //遍历到最后一位分割结束
result.add(new ArrayList<>(path));
return;
}
for(int i = startIndex; i < s.length(); i++){
if(isPalindrome(s, startIndex, i)) { //判断是否是回文串,是则加入path
path.add(s.substring(startIndex, i + 1));
}else continue; //不是剪枝
backtracking(s, i+1);
path.removeLast();
}
}
boolean isPalindrome(String s , int startIndex, int endIndex){
char[] c = s.toCharArray();
for(int i = startIndex; i <= endIndex; i++){
if(c[i] != c[startIndex])
return false;
}
return true;
}
public List<List<String>> partition(String s) {
backtracking(s, 0);
return result;
}
求字符串的所有子串
List<String> result = new ArrayList<>();
String path ="";
void backtracking(String s, int startIndex){
if(startIndex == s.length()){
return;
}
for(int i = startIndex; i < s.length(); i++){
char[] c = s.toCharArray();
path = path + c[i];
result.add(path);
backtracking(s, i + 1);
path = path.substring(0,path.length()-1);
}
}
public List<String> combineAll(String s){
backtracking(s, 0);
return result;
}
784.字母大小写全排列
每次都将现在的字符串加入结果,
List<String> re = new ArrayList<>();
int dis = 'A' - 'a';
public List<String> letterCasePermutation(String s) {
if(s.length() == 0) return re;
char[] c = s.toCharArray();
backtracking(c , 0);
return re;
}
void backtracking(char[] c, int startIndex){
re.add(String.valueOf(c));
for(int i = startIndex; i < c.length; i++){
if (Character.isDigit(c[i])) continue;
if (Character.isLowerCase(c[i])){
c[i] = (char)(c[i] + dis);
backtracking(c , i+1);
c[i] = (char)(c[i] - dis);
}else {
c[i] = (char)(c[i] - dis);
backtracking(c , i+1);
c[i] = (char)(c[i] + dis);
}
}
}
//回溯 字母ASCII: A 0100 0001 a 01100 0001 第五位异或即可实现转化
private void backTrack(char[] chars, int start){
res.add(String.valueOf(chars));
for(int i = start; i < chars.length;i++){
if(chars[i] > '9'){
chars[i] ^= 32;
backTrack(chars,i+1);
chars[i] ^= 32;
}
}
}