学习目标:
每天复习代码随想录上的题目1-2道算法(时间充足可以继续)
今日碎碎念:
1)滴滴开了暑期实习。
2)今天开始是回溯篇,然后是贪心以及dp,保持打卡!加油啦!
3)今天要做的事情就是,完成算法打卡,然后总结实习的工作,整理好自己的思路,应对后面可能的面试。
力扣刷题
算法
力扣77:77. 组合
未剪枝优化
class Solution {List<List<Integer>> res;List<Integer> list;public List<List<Integer>> combine(int n, int k) {res = new ArrayList<>();list = new ArrayList<>();back(n,k,1);return res;}public void back(int n,int k,int startIndex){//对于回溯最重要的就是确定终止条件if(list.size() == k){//如果小结果集里面的个数为k,就表示要回溯了res.add(new ArrayList<Integer>(list));return;}//如果没满k,就得继续加元素到小结果集里面for(int i = startIndex;i<=n;i++){list.add(i);//进入下一轮选择back(n,k,i+1);//要把添加进去的末尾元素去除list.remove(list.size()-1);}}
}
剪枝优化
解答思路:
1)当我们继续去找元素的时候有个隐性条件,就是我们最终的小结果集的数量一定得满足k,如果我剩下的数量无法满足k,那就没必要往后找了
2)比如,n=4,k=4的情况下,不难想出我们的小结果集只有1234这一种情况,而不可能会出现234这种情况。那么当我挑出来了1234这种情况的时候,判断后续数量很明显长度最大为3,不满足k,因此没必要继续遍历
class Solution {List<List<Integer>> res;List<Integer> list;public List<List<Integer>> combine(int n, int k) {res = new ArrayList<>();list = new ArrayList<>();back(n,k,1);return res;}public void back(int n,int k,int startIndex){//对于回溯最重要的就是确定终止条件if(list.size() == k){//如果小结果集里面的个数为k,就表示要回溯了res.add(new ArrayList<Integer>(list));return;}//如果没满k,就得继续加元素到小结果集里面//剪枝说明:如果剩下的数量不足以组成我要求的list了,就没必要往后走了for(int i = startIndex;i<=n-(k-list.size())+1;i++){list.add(i);//进入下一轮选择back(n,k,i+1);//要把添加进去的末尾元素去除list.remove(list.size()-1);}}
}
力扣216:216. 组合总和 III
解答思路:
1)与上道题思路是类似的,多了剪枝判断而已
class Solution {List<List<Integer>> res;List<Integer> list;public List<List<Integer>> combinationSum3(int k, int n) {res = new ArrayList<>();list = new ArrayList<>();back(k,n,1,0);return res;}public void back(int k,int n,int index,int sum){//剪枝:如果当前和已经大于n,说明不需要往后走了,因为题目给定的集合是有序的if(sum > n) return;//终止条件:小结果集为k就退出,如果sum为n就加入结果集if(list.size() == k){if(sum == n) res.add(new ArrayList<>(list));return;}//开始回溯以及剪枝。剪枝同77题,后面的元素不足以满足数量就不需要继续遍历了for(int i = index;i<=9-(k-list.size())+1;i++){list.add(i);//计算当前总和sum+=i;back(k,n,i+1,sum);//回溯list.remove(list.size()-1);sum-=i;}}
}
力扣17:17. 电话号码的字母组合
解答思路:看注释即可
class Solution {//设置全局列表存储最后的结果List<String> list = new ArrayList<>();public List<String> letterCombinations(String digits) {if (digits == null || digits.length() == 0) {return list;}//初始对应所有的数字,为了直接对应2-9,新增了两个无效的字符串""String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};back(digits,numString,0);return list;}//大量拼接用StringBuilderStringBuilder sb = new StringBuilder();public void back(String digits,String[] numString,int index){//终止条件:index是记录从digits里面选取第几个元素if(index == digits.length()){list.add(sb.toString());return;}//取出当前按下的数字代表的字符串String str = numString[digits.charAt(index)-'0'];for(int i = 0;i<str.length();i++){sb.append(str.charAt(i));back(digits,numString,index+1);sb.deleteCharAt(sb.length()-1);}}
}
力扣39:39. 组合总和
解答思路:看注释即可
class Solution {List<List<Integer>> res;//大结果集List<Integer> list;//小结果集public List<List<Integer>> combinationSum(int[] candidates, int target) {res = new ArrayList<>();list = new ArrayList<>();//因为原数组是没有排序的,先对原数组进行排序Arrays.sort(candidates);back(candidates,target,0,0);return res;}//参数:数组,目标和,当前和,当前位置(下标)public void back(int[] candidates,int target,int sum,int index){//终止条件: sum == targetif(sum == target){//将小结果集加入大结果集res.add(new ArrayList<>(list));return;}//因为每个数字可以无限制重复被选取,所以index得传入ifor(int i = index;i<candidates.length;i++){if(sum+candidates[i] > target) break;list.add(candidates[i]);back(candidates,target,sum+candidates[i],i);list.remove(list.size()-1);}}
}