代码随想录算法训练营第二十七天| 93.复原IP地址 78.子集 90.子集II

文档讲解:代码随想录

视频讲解:代码随想录B站账号

状态:看了视频题解和文章解析后做出来了

93.复原IP地址

class Solution:
    def isvalid(self, s, start, end):
        if start > end:
            return False

        if s[start] == '0' and start != end:
            return False

        num = int(s[start:end+1])
        return num <= 255

    def backtracking(self, s, path, result, startindex):
        if startindex == len(s) and len(path) == 4:
            result.append('.'.join(path))
            return

        if len(path) > 4:
            return

        for i in range(startindex, min(startindex + 3, len(s))):
            if self.isvalid(s, startindex, i):
                path.append(s[startindex:i+1])
                self.backtracking(s, path, result, i+1)
                path.pop()

        return result

    def restoreIpAddresses(self, s: str) -> List[str]:
        res = self.backtracking(s, [], [], 0)
        return res

第一步:确定函数参数,老几样。

第二步:确定终止条件。这道题的终止条件有两个:

1. startindex==len(s),也就是说已经遍历到了s的最后一个元素。如果不加这个条件那么就无法保证用到s的所有元素,255255255255可能会返回2.5.5.2作为结果,这样就不符合题意了。

2.len(path) == 4,确保path里只有4个元素。因为我们的分割逻辑是有可能分割出多于4个ip部分或少于4个ip部分的,所以这个终止条件也十分有必要。后面的剪枝也是使用了len(path) > 4,这样255255255255再被分割成2.5.5.2.5的时候就会终止了。

第三步:确定单层逻辑。首先需要建立一个isvalid函数来验证当前分割的ip是否符合条件,这个函数有三种不合法情况需要判断:

1. 当start > end。

2. 当字符串由0开头,且0不是最后一位。

3. 字符串代表的数字大于255。

递归的时候传入path和result,startindex++因为不能使用相同元素。

 时间复杂度: O(3^4):IP地址最多包含4个数字,每个数字最多有3种可能的分割方式,则搜索树的最大深度为4,每个节点最多有3个子节点。

 空间复杂度: O(n)

 78.子集

class Solution:
    def backtracking(self, nums, path, result, startindex):
        result.append(path[:])

        for i in range(startindex, len(nums)):
            path.append(nums[i])
            self.backtracking(nums, path, result, i+1)
            path.pop()

        return result

    def subsets(self, nums: List[int]) -> List[List[int]]:
        res = self.backtracking(nums, [], [], 0)
        return res

这道题唯一区别就是没有终止条件,只要是进入递归那path必定是一个解。

题目里要求了结果集的去重,但因为题目给定的input全是unique value,所以并不需要任何去重操作。这道题除这两点之外就没什么好说的了。

 时间复杂度: O(n * 2^n)

 空间复杂度: O(n)

90.子集II

class Solution:
    def backtracking(self, nums, path, result, startindex):
        result.append(path[:])

        for i in range(startindex, len(nums)):
            if i > startindex and nums[i] == nums[i-1]:
                continue
            path.append(nums[i])
            self.backtracking(nums, path, result, i+1)
            path.pop()

        return result

    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        nums = sorted(nums)
        res = self.backtracking(nums, [], [], 0)
        return res

子集的两道题和昨天那组题很类似,子集II唯一区别就是题目input中可能存在重复element。那么按照昨天的去重逻辑,先给input排序,然后在树层维度上,如果i>startindex且nums[i] == nums[i-1],就continue。

[1,1,2],在树层阶段遍历第二个1的时候,直接跳过。i>startindex保证了树层。

有了剪枝,实际时间复杂度要比这个少。

时间复杂度: O(n * 2^n)

 空间复杂度: O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值