打卡Day25
1.93.复原IP地址
我的思路:按照昨天分割回文子串的思路,只是把判断是否是回文子串换成了判断数值在0~255之间,但是忘记了限制IP地址的数字只有4个。
题解思路:回溯算法将所有可能性搜出来,然后需要定义一个函数来判断分割出来的是否合法。递归终止条件,本题明确要求分成四段,所以不能用切割线切到最后作为终止条件,要使用分割的段数作为终止条件。判断子串是否合法主要考虑三点,段位以0为开头的数字不合法、段位里有非正整数字符不合法、段位如果大于255不合法。
class Solution(object):
def restoreIpAddresses(self, s):
"""
:type s: str
:rtype: List[str]
"""
res = []
self.backtracking(s, 0, 0, res, "")
return res
def backtracking(self, s, startindex, pointsum, res, cur):
#终止条件
if pointsum == 3:
#判断第四段是否合法
if self.ishefa(s, startindex, len(s) - 1):
cur += s[startindex:]
res.append(cur)
return
for i in range(startindex, len(s)):
if self.ishefa(s, startindex, i):
sub = s[startindex:i + 1]
self.backtracking(s, i + 1, pointsum + 1, res, cur + sub + '.')
def ishefa(self, s, left, right):
#左闭右闭
if left > right:
return False
#开头是否为0
if s[left] == '0' and left != right:
return False
#是否有非数字字符以及大于255
num = 0
for i in range(left, right + 1):
if not s[i].isdigit():
return False
num = 10 * num + int(s[i])
if num > 255:
return False
return True
class Solution(object):
def restoreIpAddresses(self, s):
"""
:type s: str
:rtype: List[str]
"""
res = []
self.backtracking(s,0, res, [])
return res
def backtracking(self, s, startindex, res, path):
if startindex == len(s) and len(path) == 4:
res.append('.'.join(path))
return
if len(path) > 4:
return
for i in range(startindex, min(len(s), startindex + 3)):
#IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,对应的搜索树每个节点最多有3个子节点
if self.ishefa(s, startindex, i):
sub = s[startindex:i + 1]
path.append(sub)
self.backtracking(s, i + 1, res, path)
path.pop()
def ishefa(self, s, left, right):
if left > right:
return False
if s[left] == '0' and left != right: #0要用‘’,表示是字符0
return False
num = int(s[left: right + 1])
return 0 <= num <= 255
2.78.子集
子集问题是收集所有节点的结果。
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
path = []
self.backtracking(nums, 0, res, path)
return res
def backtracking(self, nums, startindex, res, path):
res.append(path[:])#收集子集,要写在终止条件之上,不然会漏掉
#终止条件,可以不写
if startindex >= len(nums):
return
for i in range(startindex, len(nums)):
path.append(nums[i])
self.backtracking(nums, i + 1, res, path)
path.pop()
3.90.子集II
这道题和上一题不一样的地方就在于元素有重复的,需要去重。去重需要排序。
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
nums.sort()
self.backtracking(nums, 0, res, [])
return res
def backtracking(self, nums, startindex, res, path):
res.append(path[:])
if startindex >= len(nums):
return
for i in range(startindex, len(nums)):
#去重
if i > startindex and nums[i] == nums[i - 1]:
continue
path.append(nums[i])
self.backtracking(nums, i + 1, res, path)
path.pop()
使用used数组:
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
used = [False] * len(nums)
res = []
nums.sort()
self.backtracking(nums, 0, res, [], used)
return res
def backtracking(self, nums, startindex, res, path, used):
res.append(path[:])
#终止条件
if startindex >= len(nums):
return
for i in range(startindex, len(nums)):
#去重
if i > startindex and nums[i] == nums[i - 1] and not used[i - 1]:
continue
used[i] = True
path.append(nums[i])
self.backtracking(nums, i + 1, res, path, used)
path.pop()
used[i] = False
还可以利用集合来去重。
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
res = []
nums.sort()
self.backtracking(nums, 0, res, [])
return res
def backtracking(self, nums, startindex, res, path):
res.append(path[:])
ueset = set()
for i in range(startindex, len(nums)):
if nums[i] in ueset:
continue
ueset.add(nums[i])
path.append(nums[i])
self.backtracking(nums, i + 1, res, path)
path.pop()