第11天,十分痛苦,回溯前期理解太苦涩了,而且程序怎么运行的是比较不懂的,回去吃完饭拉上小钟两个人看了两个小时,打了无数断点想看明白怎么计算出结果的,还好理解了现在。关键点在于递归后需要回溯状态!!!
先看第一题组合
class Solution {
public List<List<Integer>> combine(int n, int k) {
//存放最终返回结果
List<List<Integer>> array =new ArrayList<>();
//队列类型path存放每一种可能的结果
Deque<Integer> path = new ArrayDeque<>();
if (k <= 0 || n < k) {
return array;}
dfs(n,k,1,array,path);
return array;
}
//回溯
public void dfs (int n,int k,int begin,List<List<Integer>> array,Deque<Integer> path){
//如果path长度达到要求,返回出去
if(path.size() == k){
array.add(new ArrayList<>(path));
return;
}
//递归+回溯
for(int i = begin;i<=n;i++){
path.add(i);
//递归
dfs(n,k,i+1,array,path);
//回溯
path.removeLast();
}
}
}
第二题全排列
class Solution {
public List<List<Integer>> permute(int[] nums) {
//存放最终结果
List<List<Integer>> res = new ArrayList<>();
int len = nums.length;
//穿上小马甲,用过的就不用了
boolean[] used = new boolean[len];
//path存放每一种可能
Deque<Integer> path = new ArrayDeque<>(len);
dfs(nums, res, used, 0,path);
return res;
}
public static void dfs(int[] nums,List<List<Integer>> res,boolean[] used,int depth,Deque<Integer> path){
int len = nums.length;
//如果长度达到要求,path添加到res里
if(depth==len){
res.add(new ArrayList<>(path));
return;
}//递归加回溯
for(int i=0;i<len;i++){
//只有没用过的才给进
if(!used[i]){
path.add(nums[i]);
used[i] = true;
//递归
dfs(nums,res,used,depth+1,path);
//回溯
path.removeLast();
used[i] = false;
}
}
}
}
第三题字母大小写全排列
class Solution {
List<String> list = new ArrayList();
public List<String> letterCasePermutation(String s) {
getStr(0, s, new StringBuffer());
return list;
}
public void getStr(int index, String s, StringBuffer sb){
if(index == s.length()){
list.add(sb.toString());
return;
}
char ch = s.charAt(index);
sb.append(ch);
getStr(index + 1, s, sb);
sb.deleteCharAt(sb.length() - 1);
// 判断是否是字符,如果是,则转换大小写
if(!Character.isDigit(ch)){
ch = (char)(ch - 'a' >= 0 ? ch - 32 : ch + 32);
sb.append(ch);
getStr(index + 1, s, sb);
sb.deleteCharAt(sb.length() - 1);
}
}
}