力扣每日打卡8月9日打卡(93. 复原IP地址(中等))

给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。

有效的 IP 地址正好由四个整数(每个整数位于 0 到 255 之间组成),整数之间用 ‘.’ 分隔。

示例:

输入: “25525511135”
输出: [“255.255.11.135”, “255.255.111.35”]

链接:https://leetcode-cn.com/problems/restore-ip-addresses

==================================================

方法一:递归

思路与算法

由于我们需要找出所有可能复原出的 IP 地址,因此可以考虑使用递归的方法,对所有可能的字符串分隔方式进行搜索,并筛选出满足要求的作为答案。

设题目中给出的字符串为 ss。我们用递归函数 \textit{dfs}(\textit{segId}, \textit{segStart})dfs(segId,segStart) 表示我们正在从 s[\textit{segStart}]s[segStart] 的位置开始,搜索 IP 地址中的第 \textit{segId}segId 段,其中 \textit{segId} \in {0, 1, 2, 3}segId∈{0,1,2,3}。由于 IP 地址的每一段必须是 [0, 255][0,255] 中的整数,因此我们从 \textit{segStart}segStart 开始,从小到大依次枚举当前这一段 IP 地址的结束位置 \textit{segEnd}segEnd。如果满足要求,就递归地进行下一段搜索,调用递归函数 \textit{dfs}(\textit{segId} + 1, \textit{segEnd} + 1)dfs(segId+1,segEnd+1)。

特别地,由于 IP 地址的每一段不能有前导零,因此如果 s[\textit{segStart}]s[segStart] 等于字符 00,那么 IP 地址的第 \textit{segId}segId 段只能为 00,需要作为特殊情况进行考虑。

在递归搜索的过程中,如果我们已经得到了全部的 44 段 IP 地址(即 \textit{segId} = 4segId=4),并且遍历完了整个字符串(即 \textit{segStart} = |s|segStart=∣s∣,其中 |s|∣s∣ 表示字符串 ss 的长度),那么就复原出了一种满足题目要求的 IP 地址,我们将其加入答案。在其它的时刻,如果提前遍历完了整个字符串,那么我们需要结束搜索,回溯到上一步。

链接:https://leetcode-cn.com/problems/restore-ip-addresses/solution/fu-yuan-ipdi-zhi-by-leetcode-solution/

======================================================
要注意循环终止的几个条件:
1、如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
2、如果还没有找到 4 段 IP 地址就已经遍历完了字符串,那么提前回溯
3、由于不能有前导零,如果当前数字为 0,那么这一段 IP 地址只能为 0

下面两段话的等价的都是为了判断addr的值是否在0 - 255之间
addr = addr * 10 + (ord(s[segEnd]) - ord(“0”))
if 0 < addr <= 0xFF:
我将其进行了改动便于理解
addr = addr * 10 + int(s[segEnd])
if 0 < addr <= 255:

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        # 递归 
    
        SEG_COUNT = 4
        ans = list()
        segments = [0] * SEG_COUNT  #  
        
        def dfs(segId: int, segStart: int): # segId 0123,segStart 遍历到的字符位置
            # 如果找到了 4 段 IP 地址并且遍历完了字符串,那么就是一种答案
            if segId == SEG_COUNT:
                if segStart == len(s):
                    ipAddr = ".".join(str(seg) for seg in segments)
                    ans.append(ipAddr)
                return
            
            # 如果还没有找到 4 段 IP 地址就已经遍历完了字符串,那么提前回溯
            if segStart == len(s):
                return

            # 由于不能有前导零,如果当前数字为 0,那么这一段 IP 地址只能为 0
            if s[segStart] == "0":
                segments[segId] = 0
                dfs(segId + 1, segStart + 1)
            
            # 一般情况,枚举每一种可能性并递归
            addr = 0
            for segEnd in range(segStart, len(s)): # 开始到结尾  segEnd
                # addr = addr * 10 + (ord(s[segEnd]) - ord("0")) # ord()函数主要用来返回对应字符的ascii码
                # if 0 < addr <= 0xFF:  # 0xFF:255 
                addr = addr * 10 + int(s[segEnd]) # ord()函数主要用来返回对应字符的ascii码
                if 0 < addr <= 255:  # 0xFF:255 
                    segments[segId] = addr # 
                    dfs(segId + 1, segEnd + 1)
                else:
                    break
        

        dfs(0, 0)
        return ans


在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值