LeetCode 「中等」93.复原 IP 地址

sankigan2025-3-4算法LeetCode

复原 IP 地址open in new window

题目描述

有效 IP 地址 正好由四个整数(每个整数位于 0255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

例如:"0.1.2.201""192.168.1.1"有效 IP 地址,但是 "0.011.255.245""192.168.1.312""192.168@1.1"无效 IP 地址。

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

示例

输入:s = "25525511135"
输出:["255.255.11.135","255.255.111.35"]

输入:s = "0000"
输出:["0.0.0.0"]

输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]

解答

  1. 定义有效 IP 段的条件:
  • 每个段必须是一个介于 0 和 255 之间的整数
  • 每个段不能以 0 开头,除非是单个 0
  1. 回溯法
  • 使用递归函数 backtrack,尝试将字符串分割成 1 到 3 位的数字
  • 如果当前路径已经包含 4 个段,并且剩余字符串为空,则说明找到了一个有效的 IP 地址
  • 如果当前路径包含 4 个段,但剩余路字符串不为空,则说明当前路径无效,直接返回
  • 如果当前路径少于 4 个段,尝试将剩余字符串的前 1 到 3 位作为新的段,并递归处理剩余部分
  1. 剪枝:
  • 如果当前段不满足条件(如大于 255 或以 0 开头),直接跳过
  • 如果剩余字符串长度大于长形成剩余段的最大可能度,直接跳过
Code
/**
 * @param {string} s
 * @return {string[]}
 */
var restoreIpAddresses = function(s) {
  const ans = [];

  const backtrack = (path, remaining) => {
    // 如果路径长度为 4 且剩余字符串为空,说明找到了一个有效解
    if (path.length === 4 && remaining.length === 0) {
      ans.push(path.join('.'));
      return;
    }

    // 剩余段数
    const remainingSegments = 4 - path.length;
    // 剩余字符串的最大长度(每段最多 3 位)
    const maxLength = remainingSegments * 3;

    // 如果剩余字符串长度超过最大长度,直接跳过
    if (remaining.length > maxLength) return;

    // 尝试将剩余字符串分割成 1-3 位的数字
    for (let i = 1; i <= Math.min(3, remaining.length); ++i) {
      const segment = remaining.slice(0, i);

      // 判断当前段是否有效
      if (isValid(segment)) {
        path.push(segment); // 选择当前段
        backtrack(path, remaining.slice(i)); // 递归处理剩余部分
        path.pop(); // 撤销选择
      }
    }
  };

  // 判断一个 IP 段是否有效
  const isValid = (segment) => {
    // 有效条件:
    // 1. 不以 0 开头(除非是单个 0)
    // 2. 数字范围在 0 - 255
    return (
      (segment.length === 1 || !segment.startsWith('0')) &&
      +segment >= 0 &&
      +segment <= 255
    );
  };

  backtrack([], s);
  return ans;
};
更新于 2025/3/20 23:23:29
ON THIS PAGE