93.复原IP地址
本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了
题目链接:
文章讲解:代码随想录
视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili
List<String> result = new ArrayList<String>(); StringBuilder stringBuilder = new StringBuilder(); public List<String> restoreIpAddresses(String s) { restoreIpAddressesHandler(s, 0, 0); return result; } // number表示stringbuilder中ip段的数量 public void restoreIpAddressesHandler(String s, int start, int number) { if (start == s.length() && number == 4) { result.add(stringBuilder.toString()); return; } // 如果start等于s的长度但是ip段的数量不为4,或者ip段的数量为4但是start小于s的长度,则直接返回 if (start == s.length() || number == 4) { return; } // 剪枝:ip段的长度最大是3,并且ip段处于[0,255] for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0 && Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) { // 如果ip段的长度大于1,并且第一位为0的话,continue if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) { continue; } stringBuilder.append(s.substring(start, i + 1)); if (number < 3) { stringBuilder.append("."); } number++; restoreIpAddressesHandler(s, i + 1, number); number--; // 删除当前stringBuilder最后一个网段,注意考虑点的数量的问题 stringBuilder.delete(start + number, i + number + 2); } }
78.子集
子集问题,就是收集树形结构中,每一个节点的结果。 整体代码其实和 回溯模板都是差不多的。
题目链接/文章讲解:代码随想录
视频讲解:回溯算法解决子集问题,树上节点都是目标集和! | LeetCode:78.子集_哔哩哔哩_bilibili
如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合 LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果 public List<List<Integer>> subsets(int[] nums) { subsetsHelper(nums, 0); return result; } private void subsetsHelper(int[] nums, int startIndex){ result.add(new ArrayList<>(path));//「遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合」。 if (startIndex >= nums.length){ //终止条件可不加 return; } for (int i = startIndex; i < nums.length; i++){ path.add(nums[i]); subsetsHelper(nums, i + 1); path.removeLast(); } }
90.子集II
大家之前做了 40.组合总和II 和 78.子集 ,本题就是这两道题目的结合,建议自己独立做一做,本题涉及的知识,之前都讲过,没有新内容。
题目链接/文章讲解:代码随想录
视频讲解:回溯算法解决子集问题,如何去重?| LeetCode:90.子集II_哔哩哔哩_bilibili
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合 LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果 boolean[] used; public List<List<Integer>> subsetsWithDup(int[] nums) { if (nums.length == 0){ result.add(path); return result; } Arrays.sort(nums); used = new boolean[nums.length]; subsetsWithDupHelper(nums, 0); return result; } private void subsetsWithDupHelper(int[] nums, int startIndex){ result.add(new ArrayList<>(path)); if (startIndex >= nums.length){ return; } for (int i = startIndex; i < nums.length; i++){ if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]){ continue; } path.add(nums[i]); used[i] = true; subsetsWithDupHelper(nums, i + 1); path.removeLast(); used[i] = false; } }