一、93.复原IP地址
题目链接:https://leetcode.cn/problems/restore-ip-addresses/
文章讲解:https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715
1.1 初见思路
- 思路也不难,按个数来将数字进行分组,然后判断分出来的IP是否合法
- 递归终止条件是什么?这个需要想明白
- IP地址有两个限制:1-单个不能超过255 2-总共只有4段
- 判断IP段是否合法的内部函数应该怎么实现?
1.2 具体实现
class Solution {List<String> result = new ArrayList<>();String tempStr = "";public List<String> restoreIpAddresses(String s) {backtracing(s,0,0);return result;}public void backtracing(String str,int startIndex,int pointNum){if(pointNum==3){if(isValid(str,startIndex,str.length()-1)){tempStr+=str.substring(startIndex,str.length());result.add(tempStr);tempStr = tempStr.substring(0,startIndex);}return;}for(int i=startIndex;i<str.length();i++){if(isValid(str,startIndex,i)){String t1=tempStr;tempStr+=str.substring(startIndex,i+1)+".";pointNum++;backtracing(str,i+1,pointNum);pointNum--;tempStr = t1;}else{break;}}}// 判断字符串s在左闭⼜闭区间[start, end]所组成的数字是否合法private Boolean isValid(String s, int start, int end) {if (start > end) {return false;}if (s.charAt(start) == '0' && start != end) { // 0开头的数字不合法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) { // 如果⼤于255了不合法return false;}}return true;}
}
1.3 重难点
- 使用变量pointNum,记录添加逗点的数量,来作为判断递归终止条件
二、78.子集
题目链接:https://leetcode.cn/problems/subsets/
文章讲解:https://programmercarl.com/0078.%E5%AD%90%E9%9B%86.html
视频讲解:https://www.bilibili.com/video/BV1U84y1q7Ci
2.1 初见思路
- 常规递归题目
2.2 具体实现
`class Solution {
List<List> result = new ArrayList<>();// 存放符合条件结果的集合
LinkedList 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();}
}
}`## 2.3 重难点
- 这里path 使用LinkedList类,原因是这里频繁需要进行删除链表的最后一个元素,如果使用ArrayList的话,肯定效率没有LinkedList高,ArrayList底层是数组,查询快,LinkedList底层是链表,增删快;
三、 90.子集II
题目链接:https://leetcode.cn/problems/subsets-ii/
文章讲解:https://programmercarl.com/0090.%E5%AD%90%E9%9B%86II.htm
视频讲解:https://www.bilibili.com/video/BV1vm4y1F71J/
3.1 初见思路
- 包含重复元素,把原数组排序后,然后使用startIndex来控制
- 排序后,相同的元素不重复处理
3.2 具体实现
class Solution {List<List<Integer>> res = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();public List<List<Integer>> subsetsWithDup(int[] nums) {Arrays.sort(nums);subsetsWithDupHelper(nums, 0);return res;}private void subsetsWithDupHelper(int[] nums, int start) {res.add(new ArrayList<>(path));for (int i = start; i < nums.length; i++) {// 跳过当前树层使用过的、相同的元素if (i > start && nums[i - 1] == nums[i]) {continue;}path.add(nums[i]);subsetsWithDupHelper(nums, i + 1);path.removeLast();}}}