有效 IP 地址 正好由四个整数(每个整数位于 0
到 255
之间组成,且不能含有前导 0
),整数之间用 '.'
分隔。
"0.1.2.201"
和 "192.168.1.1"
是 有效 IP 地址,但是 "0.011.255.245"
、"192.168.1.312"
和 "[email protected]"
是 无效 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