LeetCodeCampsDay24回溯part03
LeetCodeCampsDay24回溯part03
再次使用了去重复的技巧,其中78,90两题目像是77.组合的变体,都是每次向path添加一个元素的类型;
而93 复原ip以及131. 分割回文串都是每次向path添加多个元素的类型
93. 复原 IP 地址
https://leetcode.cn/problems/restore-ip-addresses/
有效 IP 地址 正好由四个整数(每个整数位于 0
到 255
之间组成,且不能含有前导 0
),整数之间用 '.'
分隔。
- 例如:
"0.1.2.201"
和"192.168.1.1"
是 有效 IP 地址,但是"0.011.255.245"
、"192.168.1.312"
和"192.168@1.1"
是 无效 IP 地址。
给定一个只包含数字的字符串 s
,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s
中插入 '.'
来形成。你 不能 重新排序或删除 s
中的任何数字。你可以按 任何 顺序返回答案。
示例 1:
1 | 输入:s = "25525511135" |
示例 2:
1 | 输入:s = "0000" |
示例 3:
1 | 输入:s = "101023" |
提示:
1 <= s.length <= 20
s
仅由数字组成
回溯思路
本题难度还是有的,但在做了131.分割回文串
后,会发现这两个题目思路是相似的
在131.里,需要先在for循环里判断 s[start, i+1]是否是回文串,如果是再添加到path里;而这题目也是如此,先判断s[start, i+1]是否是合规的数字(比如数字不大于255,如果0开头则必须只能有0,数字长度不大于4);如果合规,再将数字添加到path里,再纵向搜索,再弹出以回溯;
- 输入输出:输入字符串,以及startIndex, 和深度(因为ip最多四个整数,所以深度只有4,depth等于5时需要收割结果)
- 终止条件:当startIndex小于len(s)时,需要判断如果深度已经为4且len(s[startIndex:])大于3(即明显会有多余的数字不会被处理),直接返回,从而保证deepth==5时,一定是可以收割结果的;当startIndex不小于len(s),且depth等于5,此时才将结果添加到res
- 单层逻辑:先判断s[start, i+1]是否是合规的数字,如果合规,再将数字添加到path里,再纵向搜索,再弹出以回溯;
131.和本题都是每次将s[start: i+1]子串添加到path里,而最早做的77.组合
以及下面的78.子集
每次只用添加一个元素s[i]到path里
另外,这里的深度,可以用len(self.path[:]) == 4 来判断,只要保证只有当self.path长度为4时才能收割结果。
回溯代码
- 时间复杂度: O(3^4),IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点。
- 空间复杂度: O(n)
1 | class Solution: |
78. 子集
https://leetcode.cn/problems/subsets/
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
1 | 输入:nums = [1,2,3] |
示例 2:
1 | 输入:nums = [0] |
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums
中的所有元素 互不相同
回溯思路
- 这题,需要把所有可能的子集都放在res里,本质上是遍历所有可能,在
77组合
里是求’k’个数的组合,那题目的终止条件(添加到res的条件)是len(path) == k,比如下图所示,只有当path里装了2个时,才将结果放在res;
而本题需要将所有遍历结果都装到res,所以它的终止条件(将结果放在res的条件)是空
所以本题的
- 输入输出:输入列表和起点下标,无返回值
- 终止条件:无
- 单层逻辑:添加一个元素s[i]到path里,递归下一层,弹出s[i]以回溯
回溯代码
1 | class Solution: |
90. 子集 II
https://leetcode.cn/problems/subsets-ii/
给你一个整数数组 nums
,其中可能包含重复元素,请你返回该数组所有可能的 子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
1 | 输入:nums = [1,2,2] |
示例 2:
1 | 输入:nums = [0] |
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
回溯思路
- 这题目和
40.组合总和II
以及78.子集
有点像,不同点是本题需要去重复(去重复的思路和40.组合总和II
一样,不过我记得这种需要让nums[i]!=nums[i-1]的思路在之前的题目也遇到过) - 本题和
78.子集
相比,只添加了这个去重复的约束条件,其它代码一样
回溯代码
- 时间复杂度: O(n * 2^n)
- 空间复杂度: O(n)
1 | class Solution: |