一、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();
        }
    }
}
3.3 重难点




















