代码随想录第二十三天| 复原IP地址 |子集| 子集 II

复原IP地址

这一题是今天最难的一题,首先需要分割字符串,然后还要判断分割出来的子串是否合法。这里分割字符串需要解决的问题有:如何只分四段,而且在这四段中间加上逗点。其次就是判断子串的合法性。

解决分割字符串和加逗点的问题:在之前的二叉树章节,收集路径总和是用stringbuilder收集路径值,在终止条件中遍历stringbuilder在其中加上箭头。而在本题中,直接在单层逻辑处理中对字符串作处理,在符合条件的分割出来的子串后面加上逗点构成新的字符串。终止条件的判断逻辑也是使用了逗点,这里用逗点数作为终止条件,当存在三个逗点后,且最后的子串也符合条件的话,则将整个加了逗点的新字符串放入结果集中,若是不符合条件,则进行回溯,同时删除之前添加的逗点,重新分割子串。

class Solution {
    List<String> res=new ArrayList();
    int pointsum=0;
    public List<String> restoreIpAddresses(String s) {
        if(s.length()>12){
            return res;
        }
        backtracking(s,0);
        return res;
    }
    public void backtracking(String s,int startindex){
        //startindex 搜索的起始位置,pointsum逗点的数量
        if(pointsum==3){
            //判断第四段子串是否有效,有效则放进结果中
            if(isvalid(s,startindex,s.length()-1)){
                res.add(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);
                pointsum++;
                //切割符合条件的情况下才往下递归
                backtracking(s,i+2);
                pointsum--;
                s=s.substring(0,i+1)+s.substring(i+2);
            }else{
                break;
            }
            
        }
    }
    public boolean isvalid(String s,int start,int end){
        if(start>end){//防止startindex越界到字符串后
            return false;
        }
        if(s.charAt(start)=='0'&&start!=end){
            return false;
        }
        int num=0;
        for(int i=start;i<=end;i++){
            num=num*10+(s.charAt(i)-'0');
            if(num>255){
                return false;
            }
        }
        return true;
    }
}

子集

这一题只需收集每一个路径数组即可,不需要再终止条件中收集最后的组合。使用回溯模板方法

class Solution {
    List<List<Integer>> res=new ArrayList();
    List<Integer> path=new ArrayList();
    public List<List<Integer>> subsets(int[] nums) {
        res.add(new ArrayList(path));
        backtracking(nums,0);
        return res;
    }
    public void backtracking(int[] nums,int startindex){
        if(startindex>=nums.length){
            return;
        }
        for(int i=startindex;i<nums.length;i++){
            path.add(nums[i]);
            res.add(new ArrayList(path));
            backtracking(nums,i+1);
            path.remove(path.size()-1);
        }
    }
}

子集 II

这一题是子集和昨天的需要去重的组合问题的结合版本。这里去重同样使用昨天的方法,使用一个boolean类型的used数组来进行树层去重,而不进行树枝去重。使用回溯模版方法加上标识数组。同时,这里要注意要对数组进行排序,这里的标识数组使用的前提是目标数组有序

class Solution {
    List<List<Integer>> res=new ArrayList();
    List<Integer> path=new ArrayList();
    boolean[] used;
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        used=new boolean[nums.length];
        Arrays.fill(used,false);
        Arrays.sort(nums);
        res.add(new ArrayList(path));
        backtracking(nums,0,used);
        return res;
    }
    public void backtracking(int[] nums,int startindex,boolean[] used){
        if(startindex>=nums.length){
            return;
        }
        for(int i=startindex;i<nums.length;i++){
            if(i>0&&nums[i]==nums[i-1]&&used[i-1]!=true){
                continue;
            }
            path.add(nums[i]);
            used[i]=true;
            res.add(new ArrayList(path));
            backtracking(nums,i+1,used);
            path.remove(path.size()-1);
            used[i]=false;

        }

    }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值