代码随想录 第二十七天 | ● 39. 组合总和 ● 40.组合总和II ● 131.分割回文串
leetcode:39. 组合总和 - 力扣(LeetCode)
思路:和组合一样,区别在于可以重复。如果递归里startIndex是starIndex的话,会发生后边都是由全部的数组成的,不是记录一个后往下一个走,这样就去重不了,
class Solution { LinkedList<Integer> list = new LinkedList<>(); List<List<Integer>> res = new ArrayList<>(); public List<List<Integer>> combinationSum(int[] candidates, int target) { int sum ; int startIndex; //安数组,所以说0 backtracking(candidates,target,0,0); return res; } private void backtracking(int[] candidates, int target, int sum,int startIndex) { //大于目标值退出 if(sum > target){ return; } //等于目标值记录并退出 if(sum == target){ res.add(new ArrayList<>(list)); return; } //单层逻辑,遍历一遍,每次将遇到的数sum+=,递归,-=和删除是去重也是回溯, for(int i = startIndex ; i < candidates.length; i++){ list.add(candidates[i]); sum += candidates[i]; backtracking(candidates,target,sum,i); sum -= candidates[i]; list.removeLast(); } } }
leetcode:39. 组合总和 - 力扣(LeetCode) 太狠了哥,放弃
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(); } } }
leetcode:131. 分割回文串 - 力扣(LeetCode)
[object Object]substring
(索引,索引)左闭右开,用来提取字符串的一个方法
验证是否是回文串,只需要验证从开头和结尾是否相同字母或数字
private boolean isPalindrome(String s , int a , int b){ for(int i = a , j = b;i < j ;i++,j--){ if(s.charAt(a) != s.charAt(b)){ return false; } } return true; }
思路:和组合差不多,1,验证回文串,2,回溯,这回不需要重复数字了,直接用 i +1 遍历
class Solution { LinkedList<String> list = new LinkedList(); List<List<String>> res = new ArrayList<>(); public List<List<String>> partition(String s) { int startIndex = 0; backtracking(s,0); return res; } //回溯需要字符串和下一索引 public void backtracking(String s ,int StartIndex){ //分割字符串的目的,如果起始位置大于s的大小,说明找到了一组分割方案 if(StartIndex >= s.length()){ res.add(new ArrayList<>(list)); return; } //回溯判断回文串 for(int i = StartIndex ; i < s.length() ; i++){ if(isPalindrome(s,StartIndex,i)){ list.addLast(s.substring(StartIndex,i+1)); }else { continue; } //起始位置后移,保证不重复 backtracking(s,i + 1); list.removeLast(); } } private boolean isPalindrome(String s , int a , int b){ for(int i = a , j = b;i < j ;i++,j--){ if(s.charAt(i) != s.charAt(j)){ return false; } } return true; } }