回溯算法part3

回溯算法part3

93. 复原 IP 地址 - 力扣(LeetCode)

这题真的很难,要考虑的方面太多了

从回溯函数的三要素入手:
  • 参数: Java中有StringBuilder,可以提升效率,所以
    • 参数一:元字符串的sb格式
    • 参数二:startIndex
    • 参数三:这个我没想出来,就是逗点的数量;同时逗点数量也作为后面函数终止条件来返回
  • 终止条件:逗点数量 == 3时,因为本题需要返回ip地址,一个有效的ip一定是3个逗点
  • 单层遍历逻辑:判断当前节是否有效,如果有效,就添加逗点,无效直接break终止递归
一些小细节:
  • isValid()函数的范围,可以写左闭右开,也可以左闭右闭,我写的是左闭右开

  • 终止条件中,逗点为3时,还有一段ip需要添加,此时需要判断第四段ip是否合理,然后才能返回

总体代码:
class Solution {

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

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

    public void backtracking(StringBuilder s, int startIndex, int pointNum) {
        if(pointNum == 3){
            if(isValid(s, startIndex, s.length())){
                res.add(s.toString());
            }
            return;
        }

        for(int i = startIndex; i < s.length(); i++){
            if(isValid(s, startIndex, i + 1)){
                s.insert(i + 1, ".");
                backtracking(s, i + 2, pointNum + 1);
                s.deleteCharAt(i + 1);
            }else {
                break;
            }
        }
    }

    public boolean isValid(StringBuilder s, int startIndex, int endIndex) {  //左闭右开
        if(startIndex >= endIndex){
            return false;
        }else if(s.charAt(startIndex) == '0' && endIndex - startIndex != 1){
            return false;    
        }
        int sum = 0;
        for(int i = startIndex; i < endIndex; i++){
            int digit = (s.charAt(i) - '0');
            sum = sum * 10 + digit;
        }
        if(sum >= 0 && sum <= 255){
            return true;
        }
        return false;
    }
}

78. 子集 - 力扣(LeetCode)

子集问题

标准模板题,并且本题不需要剪枝操作,因为需要所有子集,那就是遍历整颗树

唯一与模板不同是每个节点的子集都需要加入res,如图所示

代码如下:

class Solution {

    List<List<Integer>> res = new ArrayList<>();

    List<Integer> path = new ArrayList<>();
 
    public List<List<Integer>> subsets(int[] nums) {
        backtracking(nums, 0);
        return res;
    }

    public void backtracking(int[] nums, int startIndex) {
        res.add(new ArrayList<>(path));
        if(startIndex >= nums.length){ 
            return ;
        }

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

90. 子集 II - 力扣(LeetCode)

40.组合总和II 和 78.子集 ,本题就是这两道题目的结合

本人做的时候已经忘了之前的题目怎么做的

重点就是同层(for循环)去重,需要提前对nums数组排序

代码如下:

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);
        return res;
    }

    public void backtracking(int[] nums, int startIndex) {
        res.add(new ArrayList<>(path));
        if(startIndex >= nums.length){
            return ;
        }

        for(int i = startIndex; i < nums.length; i++){
            if(i > startIndex && nums[i] == nums[i - 1]){
                continue;
            }
            path.add(nums[i]);
            backtracking(nums, i + 1);
            path.removeLast();
        }
    }
}
posted @ 2025-06-17 16:33  泡芙猪  阅读(34)  评论(0)    收藏  举报