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

一、93.复原IP地址

题目链接:93. 复原 IP 地址 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——93.复原IP地址
视频讲解:回溯算法如何分割字符串并判断是合法IP?| LeetCode:93.复原IP地址_哔哩哔哩_bilibili

切割问题,并判断合法性。

树形结构:

class Solution:
    # 1. 确定递归函数的参数和返回值
    # pointsum,记录 "." 数量
    # current,记录当前构建ip地址的前缀部分
    def backtracking(self, result, s, startindex, pointsum, current):
        # 2. 确定递归终止条件
        if pointsum == 3:
            # 判断最后一段合法性
            if self.is_valid(s, startindex, len(s) - 1):
                # 添加最后一段字符串
                current += s[startindex:]
                result.append(current)
                return
            
        # 3. 确定单层递归逻辑
        for i in range(startindex, len(s)):
            # 判断切割字串[startindex, i]之间字符串的合法性
            if self.is_valid(s, startindex, i):
                sub = s[startindex:i + 1]
                pointsum += 1
                self.backtracking(result, s, i + 1, pointsum, current + sub + ".")
                pointsum -= 1                                       # 回溯

        
    # 判断合法性函数
    def is_valid(self, s, start, end):
        # 起始位置大于终止位置
        if start > end:
            return False

        # 含有前导0错
        if s[start] == '0' and start != end:
            return False

        num = 0
        for i in range(start, end + 1):
            # 遇到非数字不合法
            if not s[i].isdigit():
                return False
            
            # 大于255不合法
            num = num * 10 + int(s[i])
            if num > 255:
                return False
        return True

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

二、78.子集

题目链接:78. 子集 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——78.子集
视频讲解:回溯算法解决子集问题,树上节点都是目标集和! | LeetCode:78.子集_哔哩哔哩_bilibili

思路:所有叶子节点集合,每一层递归都要收集结果放进结果集。

class Solution:
    #1. 确定递归函数的参数和返回值
    def backtracking(self, nums, path, result, startindex):
        # 收获结果的逻辑要放在终止条件之前,如果放在下面会给最后一个元素的结果省略掉
        result.append(path[:])

        ## 2. 确定递归终止条件,终止条件可以省略
        # if startindex >= len(nums):
            # return

        # 3. 确定单层递归逻辑
        for i in range(startindex, len(nums)):
            path.append(nums[i])
            self.backtracking(nums, path, result, i + 1)
            path.pop()


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

三、90.子集II

题目链接:90. 子集 II - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——90.子集II
视频讲解:回溯算法解决子集问题,如何去重?| LeetCode:90.子集II_哔哩哔哩_bilibili

Note:为40. 组合总和II 和 78.子集知识点的结合。

class Solution:
    # 1. 确定递归函数的参数和返回值
    def backtracking(self, nums, path, result, startindex, used):
        # 2. 确定递归终止条件
        result.append(path[:])

        # 3. 确定单层递归逻辑
        for i in range(startindex, len(nums)):
            # 去重,如果当前元素与前一个元素相同且前一个元素没用过
            if i > startindex and nums[i] == nums[i - 1] and used[i - 1] == False:
                continue
            
            path.append(nums[i])
            used[i] = True
            self.backtracking(nums, path, result, i + 1, used)
            path.pop()                                              # 回溯
            used[i] = False                                         # 回溯


    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        used = [False] * len(nums)
        path = []
        result = []
        nums.sort()     # 排序
        self.backtracking(nums, path, result, 0, used)
        return result
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值