「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
题目
链接:leetcode-cn.com/problems/re…
有效 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 = "1111" 输出:["1.1.1.1"]
示例 4:
**输入:**s = "010010" 输出:["0.10.0.10","0.100.1.0"]
示例 5:
**输入:**s = "101023" 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
提示:
0 <= s.length <= 20s仅由数字组成
思路
var restoreIpAddresses = function (s) {
if (s.length > 12) return []
let result = []
fn(s, [], result)
return result
};
递归遍历
- 递归结束条件:当判断到最后一段时,如果合法直接加入到结果集
- 递归体:每一段长度可以为1、2、3,所以每次都有三种可能
function fn(remain, temp, result) {
if (temp.length === 3) {
regular(remain) && result.push([...temp, remain].join('.'))
return
}
for (let i = 1; i < 4; i++) {
regular(remain.substr(0, i)) && fn(remain.substr(i), [...temp, remain.substr(0, i)], result)
}
}
是否合法需要满足以下条件:
- 大于等于0;
- 小于等于255
- 如果是一位可以为0,如果超过一位,不能以0开头
/**
* @desc 用来判断每一段是否合法
* @param {string} s
* @return {boolean}
*/
function regular(s) {
if (!s.length) return false
return 0 <= +s && +s <= 255 && (s.length > 1 ? !!+s[0] : true)
}
思路2
- 如果所示将这个地址看成一棵树,我们一共有四个位置,我们需要对每个位置上的数字依次进行分析。
- 剪枝的条件:
- 划分的ip地址的段数>4
- 第一个字符为0并且字符的长度>1的情况下需要剪枝,比如某一位上的IP地址为02,012就不符合
- 某一位上的ip地址>255
- 需要注意的细节点,在ip地址的最后一位上没有. ,具体的代码实现为path+str+(num===3? '':'.')
代码
/**
* @param {string} s
* @return {string[]}
*/
var restoreIpAddresses = function(s) {
let res=[];
dfs(s,0,0,'');
return res;
function dfs(ip,idx,num,path){
if(num>4) return;
//当前已经划分为4段(num从0~3,所以退出条件为4)并且已经搜索到ip地址的最后一位则存入结果
if(num ===4 && idx===ip.length){
res.push(path);
}
for(let i=1;i<4;i++){
let str=ip.substring(idx,idx+i);
if(str[0]==='0' && str.length>1 || Number(str)>255) return;
dfs(ip,idx+i,num+1,path+str+(num===3? '':'.'));
}
}
};