【代码随想录Day27】回溯算法

93 复原IP地址

https://leetcode.cn/problems/restore-ip-addresses/description/

每层放一个点,横向上有取一到三位,三种取法。

关于0的逻辑是,如果首位是0那么只能取一位,如果首位不是零,那么可以取1-255之间的数。

class Solution {
    public List<String> restoreIpAddresses(String s) {
        List<String> result = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        dfs(result, sb, 0, 0, s);
        return result;
    }
    private void dfs(List<String> result, StringBuilder sb, int start, int level, String s) {
        if (start == s.length() || level == 4) {
            if (start == s.length() && level == 4) result.add(new String(sb.deleteCharAt(sb.length() - 1))); 
            return;
        }
        int len = sb.length();
        for (int end = start; end < Math.min(start + 3, s.length()); end++) {        // bug out of boundary
            String sub = s.substring(start, end + 1);
            if (end == start && s.charAt(start) == '0' || s.charAt(start) != '0' && Integer.parseInt(sub) <= 255) {
                sb.append(sub);
                sb.append('.');
                dfs(result, sb, end + 1, level + 1, s);
                sb.setLength(len);
            }
        }
    }
}

78 子集

https://leetcode.cn/problems/subsets/ 子集即为没有外部要求的组合,和组合77的做法是一样的,都有两种写法,不同的是没有和为sum或者k个的限制,做法一中不需要条件直接输出都是解。

class Solution {         //做法一,每层取一个,一个都不取时也是解,所以在每个node前都输出
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> cur = new ArrayList<>();
        dfs(nums, result, cur, 0);
        return result;
    }
    private void dfs(int[] nums, List<List<Integer>> result, List<Integer> cur, int start) {
        result.add(new ArrayList<>(cur));           //为什么这里不需要 if (start == nums.length), cur为index以后都不取的子集
        for (int i = start; i < nums.length; i++) {
            cur.add(nums[i]);
            dfs(nums, result, cur, i + 1);
            cur.remove(cur.size() -1);
        }
    }
}

class Solution {    //做法二,每层决定取或不取第index个数
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> cur = new ArrayList<>();
        dfs(result, cur, nums, 0);
        return result;
    }
    private void dfs(List<List<Integer>> result, List<Integer> cur, int[] nums, int index) {
        if (index == nums.length) {
            result.add(new ArrayList<>(cur));
            return;
        }
        dfs(result, cur, nums, index + 1);
        cur.add(nums[index]);
        dfs(result, cur, nums, index + 1);
        cur.remove(cur.size() - 1);
    }
}

90 子集II

https://leetcode.cn/problems/subsets-ii/

class Solution {         //做法一
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> cur = new ArrayList<>();
        Arrays.sort(nums);
        dfs(result, cur, nums, 0);
        return result;
    }
    private void dfs(List<List<Integer>> result, List<Integer> cur, int[] nums, int index) {
        result.add(new ArrayList<>(cur));
        for (int i = index; i < nums.length; i++) {
            // 值相同的相邻树枝,只遍历第一条
            if (i == index || nums[i] != nums[i - 1]) {        // bug, 这里 i == index 而不是 i == 0, 对这层来说 i = index肯定可以选
                cur.add(nums[i]);                              
                dfs(result, cur, nums, i + 1);
                cur.remove(cur.size() - 1);
            }
        }
    }
}

class Solution {         //做法二,取或不取,不取就相同的都不取
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        List<Integer> cur = new ArrayList<>();
        Arrays.sort(nums);
        dfs(result, cur, nums, 0);
        return result;
    }
    private void dfs(List<List<Integer>> result, List<Integer> cur, int[] nums, int index) {
        if (index == nums.length) {
             result.add(new ArrayList<>(cur));
             return;
        }
        cur.add(nums[index]);
        dfs(result, cur, nums, index + 1);
        cur.remove(cur.size() - 1);
        while (index + 1 < nums.length && nums[index] == nums[index + 1]) {
            index++;
        }
        dfs(result, cur, nums, index + 1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值