代码随想录训练营第二十八天| 93.复原IP地址 78.子集 90.子集II

93.复原IP地址

可以借鉴 131.分割回文串 

131 题的要求是:让你把字符串 s 切分成若干个合法的回文串,返回所有的切分方法。

而本题的要求是:让你把字符串 s 切分成 4 个合法的 IP 数字,返回所有的切分方法。

所以差别,便是如何判断合法的 IP 数字

代码如下:

public boolean isValid(String s, int start, int end){
        if(start > end){
            return false;
        }

        // 子串是否以 0 开头
        if(s.charAt(start) == '0' && start != end){
            return false;
        }

        // 子串例是否有非整数字符
        int num = 0;
        for(int i = start; i <= end; i++){
            if(s.charAt(i) > '9' || s.charAt(i) < '0'){
                return false;
            }
            // 子串是否大于255
            num = num * 10 + (s.charAt(i) - '0');
            if(num > 255){
                return false;
            }
        }

        return true;
    }

借用卡哥的决策树:

 完整代码如下:

class Solution {

    List<String> res = new LinkedList<>();
    List<String> track = new LinkedList<>();

    public List<String> restoreIpAddresses(String s) {
        backtrack(s, 0, track);
        return res;
    }

    public void backtrack(String s, int start, List<String> track){
        if(start == s.length() && track.size() == 4){
            res.add(String.join(".",track));
            return;
        }

        for(int i = start; i < s.length(); i++){           

            if(!isValid(s, start, i)){
                continue;
            }
            
            // 由于题中只用切成 4 个 IP数字
            // 已经分解为4个部分了,就不需要继续分解
            if(track.size() >= 4){
                break;
            }

            track.add(s.substring(start, i + 1));
            backtrack(s, i + 1, track);
            track.remove(track.size() - 1);
        }
    }

    public boolean isValid(String s, int start, int end){
        if(start > end){
            return false;
        }

        // 子串是否以 0 开头
        if(s.charAt(start) == '0' && start != end){
            return false;
        }

        // 子串例是否有非整数字符
        int num = 0;
        for(int i = start; i <= end; i++){
            if(s.charAt(i) > '9' || s.charAt(i) < '0'){
                return false;
            }
            // 子串是否大于255
            num = num * 10 + (s.charAt(i) - '0');
            if(num > 255){
                return false;
            }
        }

        return true;
    }
}

78.子集

注:子集问题便是找树的所有节点

但因为它的集合是无序的,取过的元素不会重复取,所以for仍然从start开始

决策树由下:

 可知,当剩余集合为空时,便是结束条件

完整代码如下:

class Solution {
    
    List<List<Integer>> res = new LinkedList<>();
    List<Integer> track = new LinkedList<>();

    public List<List<Integer>> subsets(int[] nums) {
        backtrack(nums, 0);
        return res;
    }

    public void backtrack(int[] nums, int start){
        // 由于子集问题就是该树的所有节点 -> 遍历这棵树的时候便把所有节点记录下来
        res.add(new LinkedList<>(track));

        if(start >= nums.length){
            return;
        }

        for(int i = start; i < nums.length; i++){
            track.add(nums[i]);

            backtrack(nums, i + 1);

            track.remove(track.size() - 1);
        }
    }
}

90.子集II

78.子集 问题区别便是有重复元素,便是不能有重复子集

所以便考虑如何避免重复元素

if(i > start && nums[i] == nums[i - 1]){
    continue;
}

决策树如下:

所以完整代码为:

class Solution {

    List<List<Integer>> res = new LinkedList<>();
    List<Integer> track = new LinkedList<>();

    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        backtrack(nums, 0);
        return res;
    }

    public void backtrack(int[] nums, int start){
        res.add(new LinkedList<>(track));

        if(start >= nums.length){
            return;
        }
        
        for(int i = start; i < nums.length; i++){
            if(i > start && nums[i] == nums[i - 1]){
                continue;
            }

            track.add(nums[i]);
            backtrack(nums, i + 1);
            track.remove(track.size() - 1);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值