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

55 阅读1分钟

93.复原IP地址

题目链接:93. 复原 IP 地址

思路:切割问题,原理上还是抽象成树形结构,然后使用回溯法。

image.png

class Solution {
    private List<String> res = new ArrayList<>();
    public List<String> restoreIpAddresses(String s) {
        backtracking(s, 0, 0);
        return res;
    }
    public void backtracking(String s, int start, int pointNum) {
        if (pointNum == 3) {
            if (isValid(s, start, s.length() - 1)) {
                res.add(s);
            } else {
                return;
            }
        }
        for (int i = start; i < s.length(); i++) {
            if (isValid(s, start, i)) {
                s = s.substring(0, i + 1) + "." + s.substring(i + 1);
                backtracking(s, i + 2, pointNum + 1);
                s = s.substring(0, i + 1) + s.substring(i + 2);
            } else {
                return;
            }
        }
    }
    public boolean isValid(String s, int start, int end) {
        if (start > end) return false; // 如果出现把.加到最后的情况,这里不加判断就会越界
        if (s.charAt(start) == '0' && start != end) return false;
        int num = 0;
        for (int i = start; i <= end; i++) {
            if (s.charAt(i) < '0' || s.charAt(i) > '9') return false;
            num *= 10;
            num += s.charAt(i) - '0';
            if (num > 255) return false;
        }
        return true;
    }
}

本题的代码在时间上仍有很大的优化空间。后续补充。

78.子集

题目链接:78. 子集

思路:回溯法,首先要将问题抽象成树形结构。注意,分割问题和组合问题收集结果是在树的叶子节点,子集问题收集结果是收集数中的所有节点

image.png

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

90.子集II

题目链接:90. 子集 II

思路:与上一题思路相同,但是要考虑去重的问题。注意,这里是要在同一个树层上进行去重,而不是在同一个树杈上进行去重

image.png

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