算法刷题 - 回溯算法part3|93.复原IP地址|78.子集|90.子集II

LeetCode - 93. 复原IP地址

复原IP地址其实和切割字符串类似,只不过在切割的时候需要在原来的字符串上判断当前截取片段的可行性并添加逗点。

class Solution {
    List<String> res = new ArrayList<>();

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

    private void backtracking(StringBuilder s, int startIdx, StringBuilder curIP, int dotNum) {
        //树的深度就是3
        if (dotNum == 3) {
            //还需判断最后一个逗点后最后一段
            if (isValidNum(s, startIdx, s.length() - 1)) {
                res.add(s.toString()); //s为添加完逗点的结果,我们在原基础上进行添加
                return;
            }
        }

        for (int i=startIdx; i < s.length(); i++) {
            //对字符串的固定区间进行判断
            if (isValidNum(s, startIdx, i)) {
                //合法的话,添加逗点,进入下一层
                s.insert(i+1, '.');
                dotNum++;
                backtracking(s, i+2, curIP, dotNum); //因为加了一个点,下一层起始idx是i+2
                dotNum--;
                s.deleteCharAt(i+1);
            };
        }
    }

    private boolean isValidNum(StringBuilder s, int startIdx, int endIdx) {
        if (startIdx > endIdx) return false;
        if (s.charAt(startIdx) == '0' && startIdx != endIdx) return false;
        long num = Long.parseLong(s.substring(startIdx, endIdx+1));
        if (num > 255) return false;
        return true;
    }
}

LeetCode - 78. 子集

解题思路:在求子集的问题上和之前的组合/组合总和问题在收集结果的方式是不太一样的。组合问题通常是在叶子节点取结果,靠的是终止条件。而子集问题应该在每一个可能的节点都要收集结果。因此在每一次能执行的回溯都需要收集结果。

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;
    }

    private void backtracking(int[] nums, int startIdx) {
        //每一次只要不直接return就都要收集结果
        res.add(new ArrayList(path));

        if (startIdx == nums.length) {
            return;
        }

        for (int i = startIdx; i < nums.length; i++) {
            path.add(nums[i]);
            backtracking(nums, i+1);
            path.removeLast();
        }
    }
}

LeetCode - 90. 子集 II

解题思路:这题是在上一题的思路上加上了去重逻辑,去重部分和昨天的组合问题思路类似。

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

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

    private void backtracking(int[] nums, int startIdx, boolean[] used) {
        res.add(new ArrayList(path));


        if (startIdx == nums.length) return;
        for (int i=startIdx; i < nums.length; i++) {
            if (i > 0 && nums[i] == nums[i-1] && !used[i-1]) continue; // duplicated in same level
            path.add(nums[i]);
            used[i] = true;
            backtracking(nums, i+1, used);
            used[i] = false;
            path.removeLast();
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值