代码随想录算法训练营day28 | 93.复原IP地址,78.子集,90.子集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函数开头.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值