28 第七章 回溯算法
● 93.复原IP地址
● 78.子集
● 90.子集II 详细布置 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
往日任务
● day 1 任务以及具体安排:https://docs.qq.com/doc/DUG9UR2ZUc3BjRUdY
● day 2 任务以及具体安排:https://docs.qq.com/doc/DUGRwWXNOVEpyaVpG
● day 3 任务以及具体安排:https://docs.qq.com/doc/DUGdqYWNYeGhlaVR6
● day 4 任务以及具体安排:https://docs.qq.com/doc/DUFNjYUxYRHRVWklp
● day 5 周日休息
● day 6 任务以及具体安排:https://docs.qq.com/doc/DUEtFSGdreWRuR2p4
● day 7 任务以及具体安排:https://docs.qq.com/doc/DUElCb1NyTVpXa0Jj
● day 8 任务以及具体安排:https://docs.qq.com/doc/DUGdsY2JFaFhDRVZH
● day 9 任务以及具体安排:https://docs.qq.com/doc/DUHVXSnZNaXpVUHN4
● day 10 任务以及具体安排:https://docs.qq.com/doc/DUElqeHh3cndDbW1Q
●day 11 任务以及具体安排:https://docs.qq.com/doc/DUHh6UE5hUUZOZUd0
●day 12 周日休息
●day 13 任务以及具体安排:https://docs.qq.com/doc/DUHNpa3F4b2dMUWJ3
●day 14 任务以及具体安排:https://docs.qq.com/doc/DUHRtdXZZSWFkeGdE
●day 15 任务以及具体安排:https://docs.qq.com/doc/DUHN0ZVJuRmVYeWNv
●day 16 任务以及具体安排:https://docs.qq.com/doc/DUHBQRm1aSWR4T2NK
●day 17 任务以及具体安排:https://docs.qq.com/doc/DUFpXY3hBZkpabWFY
●day 18 任务以及具体安排:https://docs.qq.com/doc/DUFFiVHl3YVlReVlr
●day 19 周日休息
●day 20 任务以及具体安排:https://docs.qq.com/doc/DUGFRU2V6Z1F4alBH
●day 21 任务以及具体安排:https://docs.qq.com/doc/DUHl2SGNvZmxqZm1X
●day 22 任务以及具体安排:https://docs.qq.com/doc/DUHplVUp5YnN1bnBL
●day 23 任务以及具体安排:https://docs.qq.com/doc/DUFBUQmxpQU1pa29C
●day 24 任务以及具体安排:https://docs.qq.com/doc/DUEhsb0pUUm1WT2NP
●day 25 任务以及具体安排:https://docs.qq.com/doc/DUExTYXVzU1BiU2Zl
●day 26 休息
●day 27 任务以及具体安排:https://docs.qq.com/doc/DUElpbnNUR3hIbXlY
day28
复原ip地址
class Solution {List<String> result = new ArrayList<>();StringBuilder sb = new StringBuilder();public List<String> restoreIpAddresses(String s) {//切割字符串,回溯法;建立stringbuilder用来存储合适的子段,最后加到结果集里backtricking(s,0,0);return result;}private void backtricking(String s, int index, int dotnum){//ip分四段,逗号三个判断深度结束,index判断横向结束if(dotnum == 3){//判断最后的子串是否合法if( isvalid(s,index,s.length() - 1)){sb.append(s.substring(index , s.length()));result.add(sb.toString());}return;//深度结束,不进入下一层回溯}for( int i = index; i < s.length(); i++){//宽度方向if( isvalid(s, index, i)) {sb.append(s.substring(index,i+1));//substring左闭右开sb.append('.');dotnum++;}else continue; backtricking(s,i+1,dotnum);dotnum--;//回溯,控制深度减一//sb.delete( index + dotnum , i + dotnum + 2 );//回溯前加进来的是 [index,i],然后又加进来了逗号,所以删的应该是 [index+dotnum,i+dotnum+1],左闭右开+1,故删除到i + dotnum + 2//但是这里有个问题,当整个分支结束的时候,其实除了添加的第三段,我们在dotnum==3后还加了一段,所以收割完之后不仅仅应该删除[index,i],还应该删除 [i+1 , s.length() - 1],所以直接删到最后//我的评价是不如把最后一段的判断放到dotnum==4,这样跟删除回文串一样,添加和删除都在一起//或者在result收割之后赶紧把sb复原//debug了老半天,可恶sb.delete(index + dotnum, sb.length());//123,45,}}private boolean isvalid(String s, int start, int end){if(start > end) return false;if(s.charAt(start) == '0' && start != end) return false;int sum = 0;for( int i = start; i <= end ;i++){if(s.charAt(i) > '9' || s.charAt(i) < '0') return false;sum = sum*10 + ( s.charAt(i) - '0' );}if(sum > 255) return false;return true;}}
子集
//关键在不是叶子结点收割而是节点收割class Solution {List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();//boolean[] used ;public List<List<Integer>> subsets(int[] nums) {//子集问题,回溯算法,之前是叶子结点收割结果,现在是每个节点都要收割结果//used = new boolean[nums.length];backtricking(nums,0);return result;}private void backtricking(int[] nums, int index){//不是在终止条件收割,而是有一个节点就要收割result.add(new ArrayList(path));if(index >=nums.length) return;for( int i = index; i< nums.length; i++){path.add(nums[i]);backtricking(nums,i+1);path.removeLast();}}}
子集2
//关键在去重//可以有重复元素,但是一个元素不能用两遍,而且相同的子集算一个子集class Solution {List<List<Integer>> result = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();boolean[] used ;//去重public List<List<Integer>> subsetsWithDup(int[] nums) {//子集问题,回溯算法,之前是叶子结点收割结果,现在是每个节点都要收割结果used = new boolean[nums.length];Arrays.sort(nums);//去重记得排序backtricking(nums,0);return result;}private void backtricking(int[] nums, int index){//不是在终止条件收割,而是有一个节点就要收割result.add(new ArrayList(path));if(index >=nums.length) return;for( int i = index; i< nums.length; i++){if(i>0 && nums[i] == nums[i - 1] && used[i - 1] == false) continue;//树层去重used[i] = true;path.add(nums[i]);backtricking(nums,i+1);path.removeLast();used[i] = false;}}}
感谢大佬分享:
代码随想录-算法训练营day28【回溯算法04:复原IP地址、子集】-CSDN博客