代码随想录算法训练营day28 | 93.复原IP地址,78.子集,90.子集II
- 93.复原IP地址
- 解法一:回溯
 
- 78.子集
- 解法一:回溯(单独处理空集)
- 解法二:回溯(统一处理空集)
 
- 90.子集II
- 解法一:回溯(与40.组合总和II类似)
 
- 总结
93.复原IP地址
教程视频:https://www.bilibili.com/video/BV1XP4y1U73i/?spm_id_from=333.788&vd_source=ddffd51aa532d23e6feac69924e20891
 
1、树的深度为3,可以将分割点的数量作为终止条件;
 2、返回的列表中元素是字符串,因此直接在原始字符串上进行修改;
 3、startIndex表示分割位置,同时控制横向遍历起始位置;
解法一:回溯
class Solution {
    List<String> result = new ArrayList<>();
    public List<String> restoreIpAddresses(String s) {
        if(s.length()>12)return result;
        backtracking(s,0,0);
        return result;
    }
    // startIndex: 搜索的起始位置, pointNum:添加逗点的数量
    public void backtracking(String s, int startIndex, int pointNum){
        if(pointNum==3){
            if(isValid(s,startIndex,s.length()-1)){//判断最后一个子串是否合法
                result.add(s);
                // System.out.println(s);
            }
            return;
        }
        for(int i=startIndex;i<s.length();i++){
            //判断子串是否合法
            if(isValid(s,startIndex,i)){
                s = s.substring(0,i+1)+"."+s.substring(i+1);
                System.out.println(s);
                pointNum++;
                backtracking(s,i+2,pointNum);
                //回溯
                pointNum--;
                s = s.substring(0,i+1)+s.substring(i+2);
            }else{
                break;
            }
            
        }
    }
    //判断子串是否合法,左闭右闭
    public boolean isValid(String s, int start, int end){
        //如果第三个逗号加在字符串末尾,则会出现start>=s.length()的情况,因此需要判断start>end
         if(start>end){
            return false;
        }
        if(start != end && s.charAt(start)=='0'){//以0开头
            return false;
        }
        int num = 0;
        for(int i=start;i<=end;i++){
            if(s.charAt(i)<'0' || s.charAt(i)>'9'){//含有非法字符
                return false;
            }
            //不在0~255范围中
            num = num * 10 + (s.charAt(i) - '0');
            if(num>255){
                return false;
            }
        }
        return true;
    }
}
78.子集
教程视频:https://www.bilibili.com/video/BV1U84y1q7Ci/?spm_id_from=333.788&vd_source=ddffd51aa532d23e6feac69924e20891
 
 子集问题在每次递归都要收集结果。
解法一:回溯(单独处理空集)
class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> subsets(int[] nums) {
        result.add(new ArrayList<>(path));
        backtracking(nums,0);
        return result;
    }
    public void backtracking(int[] nums,int startIndex){
        if(startIndex==nums.length){
            return;
        }
        for(int i=startIndex;i<nums.length;i++){
            path.add(nums[i]);
            result.add(new ArrayList<>(path));
            backtracking(nums,i+1);
            path.remove(path.size()-1);
        }
    }
}
解法二:回溯(统一处理空集)
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;
    }
    public void backtracking(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]);
            backtracking(nums,i+1);
            path.remove(path.size()-1);
        }
    }
}
90.子集II
教程视频:https://www.bilibili.com/video/BV1vm4y1F71J/?spm_id_from=pageDriver&vd_source=ddffd51aa532d23e6feac69924e20891
 
解法一:回溯(与40.组合总和II类似)
需要考虑树层去重和树枝去重
class Solution {
    List<List<Integer>> result =new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        backtracking(nums,0);
        return result;
    }
    public void backtracking(int[] nums, int startIndex){
        result.add(new ArrayList<>(path));
        if(startIndex>=nums.length){
            return;
        }
        for(int i=startIndex;i<nums.length; i++){
            if(i>startIndex && nums[i]==nums[i-1] )continue;
            path.add(nums[i]);
            backtracking(nums,i+1);
            path.remove(path.size()-1);
        }
    }
}
总结
子集问题需要在每个节点收集数据,因此result新增元素操作要放在backtracking函数开头.



















