题目
有效 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;
};
- 时间复杂度:,其中3表示每个数字有三种选法,4表示IP地址由四部分组成。所以需要递归四个部分,3(3(3(3)))总的可能数量就是
- 空间复杂度:。
总结
回溯算法是一种非常高效的算法,在解决一些需要进行多次回溯的问题时,可以大大提升算法的效率。