LeetCode热题(JS版) - 93. 复原 IP 地址

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

1 <= s.length <= 20
s 仅由数字组成 

思路

这道题可以用回溯算法来解决,主要思路是对字符串中每一个可能成为IP地址的位置进行判断,从而判断出所有可能的IP地址。

具体步骤如下:

  • 对字符串进行循环,每次取出一个数字作为IP地址的一部分;
  • 对取出的数字进行判断,如果长度大于1且第一位为0,则该数字不能作为IP地址的一部分;
  • 对IP地址的每一部分进行判断,如果IP地址不合法,则回溯到上一步,继续判断下一位数字;
  • 如果IP地址已经有四部分,则说明找到了一个合法的IP地址,将其存入结果数组中。
/**
 * @param {string} s
 * @return {string[]}
 */
var restoreIpAddresses = function(s) {
  let res = [];

  // 递归函数
  const backtrack = (start, subRes) => {
    // 边界情况
    // 遍历完有结果
    if (subRes.length === 4 && start === s.length) {
      res.push(subRes.join('.'));
      return;
    }
    // 遍历完无结果
    if (subRes.length === 4 || start === s.length) {
      return;
    }

    // 选择情况
    for (let i = start; i < s.length; i++) {
      // 剪枝条件,0xx
      if (s[start] === '0' && i > start) {
        break;
      }
      
      const str = s.substring(start, i + 1);
      if (+str <= 255) {
        subRes.push(str);
        backtrack(i + 1, subRes);
        subRes.pop();// 递归的回溯后需要删除当前可能得数字,从而for循环能选其他数字
      } else {
        break;
      }
    }
  };

  backtrack(0, []);
  return res;
};
  • 时间复杂度:O(34)O(3^4),其中3表示每个数字有三种选法,4表示IP地址由四部分组成。所以需要递归四个部分,3(3(3(3)))总的可能数量就是O(34)O(3^4)
  • 空间复杂度:O(1)O(1)

image.png

总结

回溯算法是一种非常高效的算法,在解决一些需要进行多次回溯的问题时,可以大大提升算法的效率。