216.组合总和III
如果把 组合问题理解了,本题就容易一些了。
题目链接/文章讲解:代码随想录
视频讲解:和组合问题有啥区别?回溯算法如何剪枝?| LeetCode:216.组合总和III_哔哩哔哩_bilibili
216:
List<List<Integer>> result= new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>(); public List<List<Integer>> combinationSum3(int k, int n) { dfs(k,n,1); return result; } public void dfs(int k, int n,int start){ if(n==0 && path.size() == k){ result.add(new ArrayList<>(path)); return; } if(n<0){ return; } for(int i = start;i<=9;i++){ if(i<=n){ path.add(i); dfs(k,n-i,i+1); path.removeLast(); } } }
39. 组合总和
本题是 集合里元素可以用无数次,那么和组合问题的差别 其实仅在于 startIndex上的控制
题目链接/文章讲解:代码随想录
视频讲解:带你学透回溯算法-组合总和(对应「leetcode」力扣题目:39.组合总和)| 回溯法精讲!_哔哩哔哩_bilibili
39:
List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>(); public List<List<Integer>> combinationSum(int[] candidates, int target) { dfs(candidates,target,0); return result; } public void dfs(int[] candidates, int target,int start){ if(target== 0){ result.add(new ArrayList<>(path)); return; } if(target<0) return; for(int i= start ; i<candidates.length;i++){ if(candidates[i]<=target){ path.add(candidates[i]); dfs(candidates,target-candidates[i],i); path.removeLast(); } } }
40.组合总和II
本题开始涉及到一个问题了:去重。
注意题目中给我们 集合是有重复元素的,那么求出来的 组合有可能重复,但题目要求不能有重复组合。
题目链接/文章讲解:代码随想录
视频讲解:回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II_哔哩哔哩_bilibili
40:
List<List<Integer>> result = new ArrayList<>(); LinkedList<Integer> path = new LinkedList<>(); public List<List<Integer>> combinationSum2(int[] candidates, int target) { Arrays.sort(candidates); dfs(candidates,target,0); return result; } public void dfs(int[] candidates, int target,int start){ if(target== 0){ result.add(new ArrayList<>(path)); return; } if(target<0) return; for(int i= start ; i<candidates.length;i++){ if(candidates[i]<=target){ path.add(candidates[i]); dfs(candidates,target-candidates[i],i+1); path.removeLast(); // 去重,跳过相同的候选数 while (i + 1 < candidates.length && candidates[i] == candidates[i + 1]) { i++; } } } }
和另外两种组合一起看:分别是选取的数组有无重复,以及能否重复使用,在于start,去重读的区别。
17.电话号码的字母组合
本题大家刚开始做会有点难度,先自己思考20min,没思路就直接看题解。
题目链接/文章讲解:代码随想录
视频讲解:还得用回溯算法!| LeetCode:17.电话号码的字母组合_哔哩哔哩_bilibili
String[] str = new String[]{"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" }; List<String> ans = new LinkedList<>(); StringBuilder re = new StringBuilder(); public List<String> letterCombinations(String digits) { dfs(digits,0); return ans; } public void dfs(String digits ,int c){ if(c == digits.length() && !re.toString().equals("")){ ans.add(re.toString()); return; } if(c>digits.length()-1){ return; } int lun = digits.charAt(c) - '0'; for(int i =0;i<str[lun].length(); i++){ re.append(str[lun].charAt(i)+""); dfs(digits,c+1); re.deleteCharAt(re.length() - 1); }
StringBuilder 是 Java 中用于操作字符串的可变类。它提供了一组方法来修改、拼接和操作字符串,而无需创建新的字符串对象。下面是一些常用的 StringBuilder 方法: append(String str):将指定的字符串添加到 StringBuilder 的末尾。 StringBuilder sb = new StringBuilder(); sb.append("Hello"); sb.append("World"); System.out.println(sb.toString()); // 输出:HelloWorld insert(int offset, String str):将指定的字符串插入到 StringBuilder 的指定位置。 StringBuilder sb = new StringBuilder("HelloWorld"); sb.insert(5, " "); System.out.println(sb.toString()); // 输出:Hello World delete(int start, int end):删除 StringBuilder 中指定范围的字符。 StringBuilder sb = new StringBuilder("Hello World"); sb.delete(5, 11); System.out.println(sb.toString()); // 输出:Hello reverse():反转 StringBuilder 中的字符顺序。 StringBuilder sb = new StringBuilder("Hello"); sb.reverse(); System.out.println(sb.toString()); // 输出:olleH replace(int start, int end, String str):用指定的字符串替换 StringBuilder 中的指定范围的字符。 StringBuilder sb = new StringBuilder("Hello World"); sb.replace(6, 11, "Java"); System.out.println(sb.toString()); // 输出:Hello Java 要使用 StringBuilder 删除最后一个字符,你可以使用 deleteCharAt() 方法。这个方法接受一个索引参数,用于指定要删除的字符的位置。将索引设置为当前字符串的长度减去 1,即可删除最后一个字符。 StringBuilder sb = new StringBuilder("Hello World"); sb.deleteCharAt(sb.length() - 1); System.out.println(sb.toString()); // 输出:Hello Worl