有效 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 中的任何数字。你可以按 任何 顺序返回答案。

- class Solution:
- def __init__(self):
- self.res = []
-
- def restoreIpAddresses(self, s: str) -> List[str]:
- # 当字符串长度大于12时,怎么切割都不合法
- if len(s) > 12:
- return []
- # 当字符串长度小于等于12时,调用切割函数进行切割
- # 开始切割的起始位置为0,“.”的个数和为0
- self.division(s, 0, 0)
- return self.res
-
- def division(self, s, startindex, pointSum):
- # s表示字符串
- # startindex表示开始切割的位置
- # pointSum表示“.”的个数,当“.”个数为3时,字符串就全部被切割了
- if pointSum == 3:
- # 当“.”的个数等于3时,已经将字符串切割为4段了
- # 校验一下最后一段的字符串是否合法
- if self.is_valid(s, startindex, len(s)):
- # 合法,就将用“.”分割后的字符串加入到res中
- self.res.append(s)
- return
- for i in range(startindex, len(s)):
- # 判断切割的字符串是否合法
- if self.is_valid(s, startindex, i+1):
- # 合法,切割字符串,加“.”
- s = s[:i+1] + "." + s[i+1:]
- # "."个数加1
- pointSum += 1
- # 调用递归,startindex为什么是i+2,因为添加了“.”,多了一个字符,整体往后移动了一个字符
- self.division(s, i+2, pointSum)
- # 回溯,为什么是i+2,因为添加了“.”,多了一个字符,整体往后移动了一个字符
- s = s[:i+1] + s[i+2:]
- pointSum -= 1
- else:
- break
-
- def is_valid(self, s, startindex, endindex):
- # 不符合要求的三种情况
- if startindex >= endindex:
- # 当切割字符串的开始位置大于结束位置,直接返回False
- return False
- if s[startindex] == "0" and startindex != endindex-1:
- # 当切割两位以上,开头字符为0,不是合法的字符串,返回False
- return False
- if not 0 <= int(s[startindex:endindex]) <= 255:
- # 当切割的字符串的值不在0到255的范围内,不是合法的字符串,返回False
- return False
- return True
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

- class Solution:
- def subsets(self, nums: List[int]) -> List[List[int]]:
- res = []
- path = [] # 存放每个符合要求的子集
- def subset(nums, startindex):
- res.append(path[:]) # 将path加入res中
- if startindex == len(nums):
- # 当开始遍历的位置等于nums的长度时,返回上层
- return
- for i in range(startindex, len(nums)):
- path.append(nums[i])
- subset(nums, i+1)
- # 回溯
- path.pop()
- subset(nums, 0)
- return res
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。

- class Solution:
- def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
- res = []
- path = []
- # used用来标记nums中对应下标的元素是否使用过,0为:没使用过,1为:已使用过
- used = [0] * len(nums)
- # 先对nums进行排序
- nums = sorted(nums)
- def subsets(nums, startindex, used):
- res.append(path[:])
- if startindex == len(nums):
- return
- for i in range(startindex, len(nums)):
- # 当i>0,前一个元素与当前元素的值相等,并且前一个元素没有被使用过
- # 说明改元素包含的组合已经在前一个元素中出现过,所以不用继续向下一层遍历了,直接进入下一次循环
- if i > 0 and nums[i-1] == nums[i] and used[i-1] == 0:
- continue
- # 将当前元素加入到path中
- path.append(nums[i])
- # 将当前元素的下标在used中对应下标的元素值修改为1,表示这个元素被使用了
- used[i] = 1
- # 递归调用,进入下一层
- subsets(nums, i+1, used)
- # 回溯
- path.pop()
- # 需要把当前元素下标在used中对应下标的元素值修改为0,表示这个元素没有被使用
- used[i] = 0
- subsets(nums, 0, used)
- return res