算法day21-回溯(3)

目录

  1. 复原IP地址
  2. 子集
  3. 子集II

一、复原IP地址——分割题

 https://leetcode.cn/problems/restore-ip-addresses/description/?envType=problem-list-v2&envId=8At1GmaZ

 

class Solution {
    List<String> res;
    StringBuilder sb;

    public List<String> restoreIpAddresses(String s) {
        res = new ArrayList<>();
        sb = new StringBuilder(s);
        dfs(0, 0);
        return res;
    }

    public void dfs(int start, int pointSum) {
        if (pointSum == 3) {
            if (isValid(sb, start, sb.length() - 1)) {
                res.add(sb.toString());
            }
            return;
        }

        for (int end = start; end < sb.length(); end++) {
            if (isValid(sb, start, end)) {
                sb.insert(end + 1, ".");
                dfs(end + 2, pointSum + 1); // end+2: 跨过插入的 '.'
                sb.deleteCharAt(end + 1);   // 回溯删除 '.'
            } else {
                break; // 剪枝:从 start 到 end 无效,更长的一定无效
            }
        }
    }

    public boolean isValid(StringBuilder sb, int start, int end) {
        if (start > end) return false;
        if (sb.charAt(start) == '0' && start != end) return false;

        int num = 0;
        for (int i = start; i <= end; i++) {
            int digit = sb.charAt(i) - '0';
            num = num * 10 + digit;
            if (num > 255) return false;
        }

        return true;
    }
}

 

二、子集——子集问题

 https://leetcode.cn/problems/subsets/?envType=problem-list-v2&envId=8At1GmaZ

 

class Solution {
    List<List<Integer>> result = new ArrayList<>();
    LinkedList<Integer> path = new LinkedList<>();
    public List<List<Integer>> subsets(int[] nums) {
        dfs(0, nums);
        return result;
    }
    public void dfs(int i, int[] nums){
        //在每个节点下都要取值
        result.add(new ArrayList<>(path));
        if(i >= nums.length){
            return;
        }
        for(int j=i; j<nums.length; j++){
            path.add(nums[j]);
            dfs(j+1, nums);
            path.remove(path.size()-1);
        }
    }

}

 

三、子集II

 https://leetcode.cn/problems/subsets-ii/?envType=problem-list-v2&envId=8At1GmaZ

   本题与上题的主要区别是原数组可能会出现重复的元素,这里需要进行【去重】操作,这里可以参考组合总和II的做法。这里一定要记得对原数组先进行排序!!

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

 

posted @ 2025-05-21 16:00  筱倩  阅读(9)  评论(0)    收藏  举报