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

文章介绍了使用回溯算法解决93.复原IP地址和78.子集以及90.子集II这三个编程问题。在IP地址恢复问题中,重点在于限制分割次数和验证每段的有效性;子集问题的关键在于在每个节点收集结果并处理重复元素。所有解决方案都利用了递归和回溯策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


总结

一、93.复原IP地址

  • 自己看到题目的第一想法

  • 看完题解之后的想法

  • 自己实现过程中遇到的问题总结

  1. startIndex一定是需要的,因为不能重复分割,记录下一层递归分割的起始位置。==本题我们还需要一个变量pointNum,记录添加逗点的数量。==因为切割的数量是有限制的,不能一直隔一位切一次。

  2. 终止条件很巧妙,是用的逗号的个数不能超过3判定的。

  3. [startIndex, i]是最后一个区间,而不是[startIndex-1,i],因为传进来的时候startindex已经加一了。

    // StringBuffer sb = new StringBuffer();
    List<String> result = new LinkedList<>();
    public List<String> restoreIpAddresses(String s) {
        backtracking(s,0,0);
        return result;
    }
    public void backtracking(String s,int startIndex,int pointNum){
        // if(startIndex>=s.length()){
        //     result.add(sb.toString());
        //     return;
        // }
        if(pointNum==3){
            if(isValid(s,startIndex,s.length()-1)){
                // result.add(sb.toString());
                result.add(s);
                return;
            }

        }

        for(int i=startIndex;i<s.length();i++){
            // String a = s.substring(startIndex,i);
            
            if(isValid(s,startIndex,i)){//如果有效
                s = s.substring(0,i+1)+"."+s.substring(i+1);//在i的后面上加一个符号
                pointNum++;
                backtracking(s,i+2,pointNum);
                pointNum--;
                s = s.substring(0,i+1)+s.substring(i+2);//把逗号去掉

            } else{
                continue;
            }


        }
    }
    public 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;
    }

11分钟

二、78.子集

  1. 本题不只是像前面在叶子结点处收集结果了,而是在每个结点都收集结果,这是很大的不同
    List<List<Integer>> result = new LinkedList<>();
    LinkedList<Integer> path = new LinkedList<>();
    public List<List<Integer>> subsets(int[] nums) {
        backtracking(nums,0);
        return result;
    }
    public void backtracking(int[] nums,int startIndex){
        result.add(new LinkedList<>(path));
        if(startIndex==nums.length){
            // result.add(new LinkedList<>(path));
            return;
        }
        // result.add(new LinkedList<>(path));
        for(int i=startIndex;i<nums.length;i++){
            path.add(nums[i]);
            backtracking(nums,i+1);
            path.removeLast();
        }
    }

40分钟

三、 90.子集II

  1. 思路:这题和上题不一样在去重逻辑上,因为数组中会出现重复数字。类似于题目组合总和三的去重思路,设计一个used数组。用于对树层去重,而不用树枝去重。
  2. used数组作为全局变量
    List<List<Integer>> result = new LinkedList<>();
    LinkedList<Integer> path = new LinkedList<>();
    boolean[] used;
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);
        used = new boolean[nums.length];
        Arrays.fill(used,false);
        backtracking(nums,0);
        return result;
    }
    public void backtracking(int[] nums,int startIndex){
        result.add(new LinkedList<>(path));
        if(startIndex==nums.length){
            // result.add(new LinkedList<>(path));
            return;
        }
        // result.add(new LinkedList<>(path));
        for(int i=startIndex;i<nums.length;i++){
            if(i>0&&nums[i]==nums[i-1]&&!used[i-1]){
                continue;
            }
            used[i]=true;
            path.add(nums[i]);
            backtracking(nums,i+1);
            path.removeLast();
            used[i]=false;
            

        }
    }

20分钟

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值