代码随想录 Day 30 | 【第七章 回溯算法part 03】93.复原IP地址、78.子集、90.子集II

一、93.复原IP地址

本期本来是很有难度的,不过 大家做完 分割回文串 之后,本题就容易很多了 

1. 题意

        有效的 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 地址。

2. 代码实现

(1)定义全局变量数组result存放合法的结果字符串。

(2)定义递归函数的参数和返回值:传入字符串s,start_index用于下层递归从哪里开始向后切割,pointSum表示一个合法的IP地址有四个整数,所以必须有3个逗号。

(3)确定终止条件:

        1)pointSum等于3的时候(此时树的深度为3),就停止递归。加了逗号之后,因为是对前面这个字符串进行合法性判断;此外还剩最后一段,需要对其进行合法性判断。

        2)对最后一段字符串进行合法性判断:if语句,调用自定义的合法性判断函数,传入字符串片段,以start_index作为分割线(起始位置),以len(s)-1为终止位置,左闭右闭区间。

        3)合法性判断函数:数字前不能有0,区间是0~255,子串里不可以有非法字符。

        4)如果合法,则收集这个字符串,最后返回。

(4)单层搜索逻辑:

        1)for循环:i 从start_index开始,到s字符串长度为止;

        2)进行合法性判断:传入左闭右闭区间,左区间start_index,右区间i。start_index固定,但i会向后移动,这个区间就是我们取出的子串。

        3)为子串加上一个逗号,插入到子串后的一个位置;

        4)pointSum加1。

        5)下一层递归:需要从i+2的位置开始,因为有一个逗号;

        6)回溯:去掉逗号,pointSum减去1。

class Solution:
    def is_valid(self, s, left, right):
        if left > right:
            return False
        if s[left] == '0' and left != right:
            return False
        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

    def backTracking(self, s, current, pointSum, start_index, result):
        if pointSum == 3:
            if self.is_valid(s, start_index, len(s)-1):
                current += s[start_index:]
                result.append(current)
            return
        for i in range(start_index, len(s)):
            if self.is_valid(s, start_index, i):
                sub = s[start_index : i+1]
                self.backTracking(s, current+sub+'.', pointSum+1, i+1, result)
            else:
                break

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

二、78.子集

子集问题,就是收集树形结构中,每一个节点的结果。 整体代码其实和 回溯模板都是差不多的。 

1. 和之前题目的不同

        每一层递归都有想要的结果,都需要加入结果集。

2. 代码实现

(1)定义一位数组path存放单个结果,二维数组result存放结果集。

(2)确定递归函数的参数和返回值:参数start_index表示本层递归从哪里开始取数,nums是传入的数组。

(3)确定终止条件:如果start_index大于等于nums数组的大小,那么终止递归,直接return。

(4)单层递归逻辑:for循环,将nums每个元素添加进入path,然后从i+1开始递归下一层,回溯将元素弹出。

class Solution:
    def backTracking(self, nums, start_index, path, result):
        result.append(path[:])

        if start_index >= len(nums):
            return

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

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

三、90.子集II

之前做了 40.组合总和II 和 78.子集 ,本题就是这两道题目的结合,建议自己独立做一做,本题涉及的知识,之前都讲过,没有新内容。 

代码实现

class Solution:
    def backTracking(self, nums, start_index, used, path, result):
        result.append(path[:])
        if start_index >= len(nums):
            return
        for i in range(start_index, len(nums)):
            if i > 0 and nums[i] == nums[i-1] and not used[i-1]:
                continue
            path.append(nums[i])
            used[i] = 1
            self.backTracking(nums, i+1, used, path, result)
            used[i] = 0
            path.pop()

    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        used = [0] * len(nums)
        path = []
        result = []
        self.backTracking(nums, 0, used, path, result)
        return result

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值