第27天打卡
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
- 所有数字(包括 target)都是正整数。
- 解集不能包含重复的组合。
示例 1:
- 输入:candidates = [2,3,6,7], target = 7,
- 所求解集为: [ [7], [2,2,3] ]
示例 2:
- 输入:candidates = [2,3,5], target = 8,
- 所求解集为: [ [2,2,2,2], [2,3,3], [3,5] ]
class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<>(); Arrays.sort(candidates); // 先进行排序 backtracking(res, new ArrayList<>(), candidates, target, 0, 0); return res; } public void backtracking(List<List<Integer>> res, List<Integer> path, int[] candidates, int target, int sum, int idx) { // 找到了数字和为 target 的组合 if (sum == target) { res.add(new ArrayList<>(path)); return; } for (int i = idx; i < candidates.length; i++) { // 如果 sum + candidates[i] > target 就终止遍历 if (sum + candidates[i] > target) break; path.add(candidates[i]); backtracking(res, path, candidates, target, sum + candidates[i], i); path.remove(path.size() - 1); // 回溯,移除路径 path 最后一个元素 } } }
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明: 所有数字(包括目标数)都是正整数。解集不能包含重复的组合。
- 示例 1:
- 输入: candidates = [10,1,2,7,6,1,5], target = 8,
- 所求解集为:
[ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]
class Solution { LinkedList<Integer> path = new LinkedList<>(); List<List<Integer>> ans = new ArrayList<>(); boolean[] used; int sum = 0; public List<List<Integer>> combinationSum2(int[] candidates, int target) { used = new boolean[candidates.length]; // 加标志数组,用来辅助判断同层节点是否已经遍历 Arrays.fill(used, false); // 为了将重复的数字都放到一起,所以先进行排序 Arrays.sort(candidates); backTracking(candidates, target, 0); return ans; } private void backTracking(int[] candidates, int target, int startIndex) { if (sum == target) { ans.add(new ArrayList(path)); } for (int i = startIndex; i < candidates.length; i++) { if (sum + candidates[i] > target) { break; } // 出现重复节点,同层的第一个节点已经被访问过,所以直接跳过 if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) { continue; } used[i] = true; sum += candidates[i]; path.add(candidates[i]); // 每个节点仅能选择一次,所以从下一位开始 backTracking(candidates, target, i + 1); used[i] = false; sum -= candidates[i]; path.removeLast(); } } }
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
示例: 输入: "aab" 输出: [ ["aa","b"], ["a","a","b"] ]
class Solution { List<List<String>> lists = new ArrayList<>(); Deque<String> deque = new LinkedList<>(); public List<List<String>> partition(String s) { backTracking(s, 0); return lists; } private void backTracking(String s, int startIndex) { //如果起始位置大于s的大小,说明找到了一组分割方案 if (startIndex >= s.length()) { lists.add(new ArrayList(deque)); return; } for (int i = startIndex; i < s.length(); i++) { //如果是回文子串,则记录 if (isPalindrome(s, startIndex, i)) { String str = s.substring(startIndex, i + 1); deque.addLast(str); } else { continue; } //起始位置后移,保证不重复 backTracking(s, i + 1); deque.removeLast(); } } //判断是否是回文串 private boolean isPalindrome(String s, int startIndex, int end) { for (int i = startIndex, j = end; i < j; i++, j--) { if (s.charAt(i) != s.charAt(j)) { return false; } } return true; } }

浙公网安备 33010602011771号