这是我参与11月更文挑战的第9天,活动详情查看:[2021最后一次更文挑战]
题目
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能从 s 获得的 有效 IP 地址 。你可以按 任何 顺序返回答案。
有效 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 地址。
示例 1:
输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"]
思路
以 "25525511135" 为例,第一步时我们有几种选择? 选 "2" 作为第一个片段 选 "25" 作为第一个片段 选 "255" 作为第一个片段 能切三种不同的长度,切第二个片段时,又面临三种选择。 这会向下分支形成一棵树,我们用 DFS 去遍历所有选择,必要时提前回溯。 因为某一步的选择可能是错的,得不到正确的结果,不要往下做了。撤销最后一个选择,回到选择前的状态,去试另一个选择。
回溯的第一个要点:选择,它展开了一颗空间树。
回溯的要点二——约束
约束条件限制了当前的选项,这道题的约束条件是:
一个片段的长度是 13
片段的值范围是 0255
不能是 "0x"、"0xx" 形式(测试用例告诉我们的)
用这些约束进行充分地剪枝,去掉一些选择,避免搜索「不会产生正确答案」的分支。
回溯的要点三——目标 目标决定了什么时候捕获答案,什么时候砍掉死支,回溯。 目标是生成 4 个有效片段,并且要耗尽 IP 的字符。 当满足该条件时,说明生成了一个有效组合,加入解集,结束当前递归,继续探索别的分支。 如果满4个有效片段,但没耗尽字符,不是想要的解,不继续往下递归,提前回溯。
代码
const res = [], path = [];
backtracking(0, 0);
return res;
function backtracking(i) {
const len = path.length;
if(len > 4) return;
if(len === 4 && i === s.length) {
res.push(path.join('.'));
return
}
for(let j = i; j < s.length; j++) {
const str = s.substr(i, j - i + 1);
if(str.length > 3 || +str > 255) break;
if(str.length > 1 && str[0] === "0") break;
path.push(str);
backtracking(j + 1);
path.pop()
}
}
};