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

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

93.复原IP地址

  1. 分割问题比较类似 自己构造一个函数用于判断分割条件
  2. 递归函数的参数一般为 startindex 或者 某些计数参数 或者 记录元素是否用过的数组
  3. 终止条件 一般为startindex走到字符串最后 或者 是完成了分割任务
  4. 每层递归时 首先判断条件 符合就 先进行分割操作 然后添加进数组
  5. 然后进入下一层递归 更新startindex
  6. 出来的时候回溯 即 删除原来添加进去的值
class Solution {
    List<String> result = new ArrayList<>();
    
    public List<String> restoreIpAddresses(String s) {
        backtracing(s,0,0);
        return result;

    }

    //startindex确定下次搜索位置  pointSum 确定点的数量
    public void backtracing(String s, int startIndex, int pointSum){
        //终止条件
        if(pointSum==3){
            if(isValid(s,startIndex,s.length()-1)){
                result.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++;
                backtracing(s,i+2,pointSum);
                //回溯用来删除节点
                pointSum--;
                s = s.substring(0,i+1)+s.substring(i+2);
            }else{
                break;
            }
        }
        return;
    }

    //左闭右闭区间
    public boolean isValid(String s, int start, int end){
        //防止startindex已经取到字符串结尾处了 
        if(start>end) return false;
        //首字符为0 但是排除只有0的情况
        if(s.charAt(start)=='0' && start!=end){
            return false;
        }
        //将每个字符变成Int
        int num = 0;
        for(int i=start;i<=end;i++){
            if(s.charAt(i)<'0' || s.charAt(i)>'9'){
                return false;
            }

            num = num*10 + (s.charAt(i)-'0');
            if(num>255){
                return false;
            }


        }
        return true;

    }
}

78. 子集

  1. 求子集 每一层递归函数的结果都加入结果集
class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> subsets(int[] nums) {
        
        backtracing(nums,0);
        return result;

    }

    public void backtracing(int[] nums, int startIndex){
        //终止条件 每一层递归函数都加入 结果集
        result.add(new ArrayList<>(path));

        //每层递归逻辑
        for(int i=startIndex; i<nums.length;i++){
            path.add(nums[i]);
            backtracing(nums,i+1);
            path.remove(path.size()-1);
        }
        return;
    }
}

90. 子集 II

  1. 此题是子集 和 树层去重 的应用
  2. 树层去重 可以用一个 boolean[]数组来记录 每次递归记录used[i]
class Solution {
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        boolean[] used = new boolean[nums.length];
        Arrays.fill(used,false);
        Arrays.sort(nums);
        backtracing(nums,0,used);
        return result;
    }


    public void backtracing(int[] nums, int startIndex, boolean[] used){
        //终止条件
        result.add(new ArrayList<>(path));

        //每层递归逻辑
        for(int i=startIndex;i<nums.length;i++){
            //树层去重
            if(i>0 && nums[i]==nums[i-1] && used[i-1]==false){
                continue;
            }
            used[i]=true;
            path.add(nums[i]);
            backtracing(nums,i+1,used);
            used[i]=false;
            path.remove(path.size()-1);
        }
        return;
    }
}

你可能感兴趣的:(Leetcode,算法,java,数据结构)