代码随想录 day 24 回溯

第七章 回溯算法part03

93.复原IP地址

本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了
题目链接/文章讲解:https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html
视频讲解:https://www.bilibili.com/video/BV1XP4y1U73i/

78.子集

子集问题,就是收集树形结构中,每一个节点的结果。 整体代码其实和 回溯模板都是差不多的。
题目链接/文章讲解:https://programmercarl.com/0078.%E5%AD%90%E9%9B%86.html
视频讲解:https://www.bilibili.com/video/BV1U84y1q7Ci

90.子集II

大家之前做了 40.组合总和II 和 78.子集 ,本题就是这两道题目的结合,建议自己独立做一做,本题涉及的知识,之前都讲过,没有新内容。
题目链接/文章讲解:https://programmercarl.com/0090.%E5%AD%90%E9%9B%86II.html
视频讲解:https://www.bilibili.com/video/BV1vm4y1F71J

93.复原IP地址

题目链接

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

解题思路

切割问题就可以使用回溯搜索法把所有可能性搜出来,和131.分割回文串 十分类似了
利用startIndex找分割点

code

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

        public void backtracking(String s ,int startIndex){
            if(path.size()==4){
                StringBuilder sb=new StringBuilder();
                sb.append(path.get(0)).append(".");
                sb.append(path.get(1)).append(".");
                sb.append(path.get(2)).append(".");
                sb.append(path.get(3));
                res.add(sb.toString());
                return;

            }

            for(int i=startIndex;i<s.length();i++){
                String str=s.substring(startIndex,i+1);
                if(!isIp(str)){
                    continue;
                }
                //剪枝 如果size是1 剩余长度大于3个3位数数则剪枝 如长度是12 i=0的加入到size=1 此时i=1 
                //那么包含i=1的数就是  s.length()-1-i+1 就是剩余的长度且包含i位置 s.length()-i
                if(path.size()==1 && s.length()-i>9){
                    break;
                }
                if(path.size()==2 && s.length()-i>6){
                    break;
                }
                if(path.size()==3 && s.length()-i>3){
                    break;
                }
                if(path.size()==3&&i!=s.length()-1){
                    continue;
                }
                path.add(str);
                backtracking(s,i+1);
                path.remove(path.size()-1);
            }

        }
        public boolean isIp(String str){
            if(str.length()>3){
                return false;
            }

            if(str.length()>1&&'0'==str.charAt(0)){
                return false;
            }
            int strToInt=Integer.parseInt(str);
            if(strToInt<0 || strToInt >255){
                return false;
            }
            return true;
        }
}

78.子集

题目链接

https://leetcode.cn/problems/subsets/description/

解题思路

组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点
不重复,startIndex=i+1 取过的元素不会重复取,写回溯算法的时候,for就要从startIndex开始,而不是从0开始

code

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));
        for(int i=startIndex;i<nums.length;i++){
            path.add(nums[i]);
            backtracking(nums,i+1);
            path.remove(path.size()-1);
        }

    }
}

90.子集II

题目链接

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

解题思路

题目说可能包含重复元素,解集不能包含重复元素的问题
通用解法,和40.组合总和II 一个解法
要排序(把相邻的元素放在一起),相同元素跳过,(否则注定会和前面的元素取出重复的子集(组合)1 1 2 第一个1取的元素已经包含第二个1取的所有元素还包含了第二个1 所以要跳过 以达到去重 “数层去重”) startIndex=i+1

code

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));
        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.remove(path.size()-1);
        }

    }
}

“树层去重”和“树枝去重” 注意去重需要先对集合排序

从图中可以看出,同一树层上重复取2 就要过滤掉,同一树枝上就可以重复取2,因为同一树枝上元素的集合才是唯一子集

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值