返回

复原IP地址:六六力扣刷题经典案例

后端

回溯经典:用六六力扣刷题还原 IP 地址

前言

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情

身为一名技术博客创作专家,我常常需要以独树一帜的观点展现事物,以此为基础构建文章。这次,我将用自己擅长的技术角度,和大家聊聊力扣刷题中的经典回溯问题——复原 IP 地址。

问题

给定一个仅包含数字 0-9 的字符串 s,请你将其还原为一个 IP 地址。一个有效的 IP 地址由四个数字组成,这些数字之间由 '.' 分隔。可以保证 s 转换后的 IP 地址为有效 IP 地址。

例如,以下字符串都可以转换为一个有效的 IP 地址:

  • "19216811" -> "192.168.1.1"
  • "1921681114" -> "192.168.1.14"
  • "1023156254" -> "10.23.15.62"

回溯算法

解决复原 IP 地址问题,我们自然而然会想到回溯算法。回溯是一种经典的深度优先搜索算法,可以遍历所有可能的情况,找到满足条件的解。

回溯算法的具体步骤如下:

  1. 从字符串的第一个字符开始,尝试以第一个字符为起点,截取长度为 1、2、3 的子字符串。
  2. 如果截取的子字符串是一个有效的 IP 段(即 0 <= 子字符串 <= 255),则继续递归处理剩下的字符串。
  3. 如果截取的子字符串不是一个有效的 IP 段,则回溯到上一步,尝试截取长度为 2、3 的子字符串。
  4. 重复步骤 1-3,直到遍历完整个字符串或找到一个有效的 IP 地址。

代码实现

根据回溯算法,我们可以写出如下代码:

def restoreIpAddresses(s):
  def is_valid_ip_segment(segment):
    if len(segment) == 0 or len(segment) > 3:
      return False
    if segment[0] == '0' and len(segment) > 1:
      return False
    ip_segment = int(segment)
    return 0 <= ip_segment <= 255

  def backtrack(index, path):
    if index == len(s) and len(path) == 4:
      result.append('.'.join(path))
      return
    
    for i in range(1, 4):
      segment = s[index:index+i]
      if is_valid_ip_segment(segment):
        backtrack(index+i, path+[segment])
  
  result = []
  backtrack(0, [])
  return result

优化

为了提高回溯算法的效率,我们可以进行一些优化:

  • 剪枝优化: 如果在回溯过程中发现当前路径无法形成一个有效的 IP 地址,则直接剪枝,避免继续递归。
  • 记忆化搜索: 将已经遍历过的子字符串和对应的 IP 段结果缓存起来,避免重复计算。

总结

复原 IP 地址问题是一个经典的回溯问题,通过使用回溯算法,我们可以找到所有可能的 IP 地址。通过优化回溯算法,我们可以提高算法的效率。

如果您是一位算法爱好者,我强烈建议您尝试自己实现复原 IP 地址问题。这将是一个很好的练习,帮助您深入理解回溯算法的原理。

SEO优化