代码随想录Day28 | 78.子集、90.子集II、93.复原IP地址 | 回溯

78 阅读1分钟

78. 子集

题目链接:78. 子集

思路: 本质上子集问题就是遍历一棵回溯树,通过保证元素之间的相对顺序不变来防止出现重复的子集,使用 start 参数控制树枝的生长避免产生重复的子集,用 track 记录根节点到每个节点的路径的值,同时在前序位置把每个节点的路径值收集起来,完成回溯树的遍历就收集了所有子集。

class Solution {

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

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

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

        for (int i = start; i < nums.length; i++) {
            track.add(nums[i]);
            backtrack(nums, i + 1);
            track.removeLast();
        }
    }
}

90. 子集 II

题目链接:90. 子集 II

思路: 我们需要进行剪枝,如果一个节点有多条值相同的树枝相邻,则只遍历第一条,剩下的都剪掉,不要去遍历。体现在代码上,需要先进行排序,让相同的元素靠在一起,如果发现 nums[i] == nums[i-1],则跳过。

   class Solution {

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

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

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

        for (int i = start; i < nums.length; i++) {
            if (i > start && nums[i] == nums[i - 1]) {
                continue;
            }
            track.addLast(nums[i]);
            backtrack(nums, i + 1);
            track.removeLast();
        }

    }
}

93.复原IP地址

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

思路: 跟分割回文串思路类似,start作为隔板,因为是ip地址,所以只能将原字符串分成4段,point记录分了几次,当point为3的时候,说明已经分成四段,此时检查最后一段字符串是否valid。每加进一个valid,判断它是否valid,如果valid的话,加入“.“。

class Solution {

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

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

    void backtrack(String s, int start, int point) {
        if (point == 3) {
            if (isValid(s, start, s.length() - 1)) {
                res.add(new String(s));
            }
            return;
        }
        for (int i = start; i < s.length(); i++) {
            if (isValid(s, start, i)) {
                s = s.substring(0, i + 1) + "." + s.substring(i + 1);
                point++;
            } else {
                continue;
            }
            backtrack(s, i + 2, point);
            point--;
            s = s.substring(0, i + 1) + s.substring(i + 2);
        }
    }

    boolean isValid(String s, int l, int r) {
        if (l > r) {
            return false;
        }
        if (s.charAt(l) == '0' && l != r) {
            return false;
        }
        int num = 0;
        for (int i = l; i <= r; i++) {
            num = num * 10 + (s.charAt(i) - '0');
            if (num > 255) {
                return false;
            }
        }
        return true;
    }
 }