复习 77 组合 注意剪枝操作,以及for loop的判断条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { List<List<Integer>> result = new ArrayList <>(); List<Integer> path = new ArrayList <>(); public List<List<Integer>> combine (int n, int k) { getPath(n , k, 1 ); return result; } private void getPath (int n, int k, int start) { if (path.size() == k){ result.add(new ArrayList <>(path)); return ; } for (int i = start; i <= n - (k - path.size()) + 1 ; i++){ path.add(i); getPath(n, k, i + 1 ); path.remove(path.size() - 1 ); } } }
17 电话号码的字母组合 注意for loop之前的值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { String[] numString = {"" , "" , "abc" , "def" , "ghi" , "jkl" , "mno" , "pqrs" , "tuv" , "wxyz" }; List<String> result = new ArrayList <>(); StringBuilder sb = new StringBuilder (); public List<String> letterCombinations (String digits) { if (digits == null || digits.length() == 0 ) return result; backTracking(digits, 0 ); return result; } private void backTracking (String digits, int start) { if (sb.length() == digits.length()){ result.add(sb.toString()); return ; } String str = numString[digits.charAt(start) - '0' ]; for (int i = 0 ; i < str.length(); i++){ sb.append(str.charAt(i)); backTracking(digits, start + 1 ); sb.deleteCharAt(sb.length() - 1 ); } } }
39 组合总和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { List<List<Integer>> result = new ArrayList <>(); List<Integer> path = new ArrayList <>(); public List<List<Integer>> combinationSum (int [] candidates, int target) { if (candidates.length == 0 ) return result; backTracking(candidates, target, 0 ); return result; } private void backTracking (int [] candidates, int target, int start) { if (target < 0 ){ return ; } if (target == 0 ){ result.add(new ArrayList <>(path)); return ; } for (int i = start; i < candidates.length; i++){ target -= candidates[i]; path.add(candidates[i]); backTracking(candidates, target, i); path.remove(path.size() - 1 ); target += candidates[i]; } } }
40 组合总和II 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Solution { List<List<Integer>> result = new ArrayList <>(); List<Integer> path = new ArrayList <>(); boolean [] used; 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 result; } private void backTracking (int [] candidates, int target, int start) { if (target == 0 ){ result.add(new ArrayList <>(path)); return ; } for (int i = start; i < candidates.length; i++){ if (target < 0 ) break ; if (i > 0 && candidates[i] == candidates[i - 1 ] && !used[i-1 ]) continue ; target -= candidates[i]; path.add(candidates[i]); used[i] = true ; backTracking(candidates, target, i + 1 ); path.remove(path.size() - 1 ); target += candidates[i]; used[i] = false ; } } }
216 组合总和III 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { List<List<Integer>> result = new ArrayList <>(); List<Integer> path = new ArrayList <>(); public List<List<Integer>> combinationSum3 (int k, int n) { backTracking(k, n, 1 ); return result; } private void backTracking (int k, int n, int start) { if (n < 0 ) return ; if (n == 0 && path.size() == k){ result.add(new ArrayList <>(path)); return ; } for (int i = start; i <= 9 - (k - path.size()) + 1 ; i++){ n -= i; path.add(i); backTracking(k, n, i + 1 ); path.remove(path.size() - 1 ); n += i; } } }
131 分割回文串 分割过程的for loop 先是切割出一个字符判断,如果是,就切割第二个,是切割第三个,完成后 第二个循环开始,直接切割两个,是移动,不是就继续第三个循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { List<List<String>> result = new ArrayList <>(); List<String> path = new ArrayList <>(); public List<List<String>> partition (String s) { backTracking(s, 0 ); return result; } private void backTracking (String s, int start) { if (start == s.length()){ result.add(new ArrayList <>(path)); return ; } for (int i = start; i < s.length(); i++){ if (isPalindrome(s, start, i)){ path.add(s.substring(start, i+1 )); backTracking(s, i + 1 ); path.remove(path.size() - 1 ); } } } private boolean isPalindrome (String s, int left, int right) { while (left <= right){ if (s.charAt(left) != s.charAt(right)) return false ; left++; right--; } return true ; } }
93 复原IP 地址 分割问题和分割回文串类似 几个重点,
代码随想录利用了一个pointnum记录逗号数量,判断 我没有用pointnum 我用Integer.parseInt()转化了string
在实际问题中,判断数字是否valid也很重要
数字起始不能有0
数字要在0 到 255中间1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 class Solution { List<String> result = new ArrayList <>(); List<Integer> path = new ArrayList <>(); public List<String> restoreIpAddresses (String s) { backTracking(s, 0 ); return result; } private void backTracking (String s, int start) { if (path.size() == 4 ){ StringBuilder sb = new StringBuilder (); for (int i = 0 ; i < path.size() - 1 ; i++){ sb.append(path.get(i)).append("." ); } sb.append(path.get(path.size() - 1 )); if (sb.length() == s.length() + 3 ){ result.add(sb.toString()); } return ; } for (int i = start; i < s.length(); i++){ if (isValid(s, start, i)){ path.add(Integer.parseInt(s.substring(start, i + 1 ))); backTracking(s, i + 1 ); path.remove(path.size() - 1 ); } else { break ; } } } private boolean isValid (String s, int start, int end) { if (start > end){ return false ; } if (s.charAt(start) == '0' && end != start) return false ; int num = 0 ; for (int i = start; i <= end; i++){ if (s.charAt(i) > '9' || s.charAt(i) < '0' ){ return false ; } num = num * 10 + (s.charAt(i) - '0' ); if (num > 255 ){ return false ; } } return true ; } }
78 子集 与组合和分割都不一样, 如果把子集问题抽象成树,就要把所有结点都记录下来
终止条件,就是start到了nums length的时候
result一直添加path
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { List<List<Integer>> result = new ArrayList <>(); List<Integer> path = new ArrayList <>(); public List<List<Integer>> subsets (int [] nums) { backTracking(nums, 0 ); return result; } private void backTracking (int [] nums, int start) { result.add(new ArrayList <>(path)); if (start >= nums.length) return ; for (int i = start; i < nums.length; i++){ path.add(nums[i]); backTracking(nums, i + 1 ); path.remove(path.size() - 1 ); } } }
90 子集II 利用组合中的去重原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { List<List<Integer>> result = new ArrayList <>(); List<Integer> path = new ArrayList <>(); boolean [] used; public List<List<Integer>> subsetsWithDup (int [] nums) { used = new boolean [nums.length]; Arrays.sort(nums); Arrays.fill(used, false ); backTracking(nums, 0 ); return result; } private void backTracking (int [] nums, int start) { result.add(new ArrayList <>(path)); if (start > nums.length){ return ; } for (int i = start; i < nums.length; i++){ if (i > 0 && nums[i] == nums[i - 1 ] && !used[i - 1 ]) continue ; used[i] = true ; path.add(nums[i]); backTracking(nums, i +1 ); used[i] = false ; path.remove(path.size() - 1 ); } } }
拓展 645 setmismatch 思路 利用loop循环查找,不等于同位置的结点,将该节点放到对应的位置上,进行排序,然后再利用for loop查找不等于该位置上的值输出result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public int [] findErrorNums(int [] nums) { int [] result = new int [2 ]; int i = 0 ; while (i < nums.length){ if (nums[nums[i] - 1 ] != nums[i]){ swap(nums, nums[i] - 1 , i); } else { i++; } } for (i = 0 ; i < nums.length; i++){ if (nums[i] != i + 1 ){ result[0 ] = nums[i]; result[1 ] = i + 1 ; } } return result; } private void swap (int [] nums, int index1, int index2) { nums[index1] ^= nums[index2]; nums[index2] ^= nums[index1]; nums[index1] ^= nums[index2]; } }