468. 验证IP地址 - 力扣(LeetCode)
发布:2021年10月7日17:15:14
问题描述及示例
编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址。
如果是有效的 IPv4 地址,返回 “IPv4” ;
如果是有效的 IPv6 地址,返回 “IPv6” ;
如果不是上述类型的 IP 地址,返回 “Neither” 。
IPv4 地址由十进制数和点来表示,每个地址包含 4 个十进制数,其范围为 0 - 255, 用(".")分割。比如,172.16.254.1;
同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。
IPv6 地址由 8 组 16 进制的数字来表示,每组表示 16 比特。这些组数字通过 (":")分割。比如, 2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以是小写。所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 address地址 (即,忽略 0 开头,忽略大小写)。
然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现(::)
的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。
同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。
示例 1:
输入:IP = “172.16.254.1”
输出:“IPv4”
解释:有效的 IPv4 地址,返回 “IPv4”
示例 2:
输入:IP = “2001:0db8:85a3:0:0:8A2E:0370:7334”
输出:“IPv6”
解释:有效的 IPv6 地址,返回 “IPv6”
示例 3:
输入:IP = “256.256.256.256”
输出:“Neither”
解释:既不是 IPv4 地址,又不是 IPv6 地址
示例 4:
输入:IP = “2001:0db8:85a3:0:0:8A2E:0370:7334:”
输出:“Neither”
示例 5:
输入:IP = “1e1.4.5.6”
输出:“Neither”
提示:
IP 仅由英文字母,数字,字符 ‘.’ 和 ‘:’ 组成。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/validate-ip-address
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
我的题解(Array.every())
总体分为三大步:
- 先将
IP
以.
或者:
为分隔符分割,获取IP
的每一个分段seg
并存于IPArr
数组中。 - 再利用
every()
函数以及自定义的验证函数(isValidIPv4Segment()
和isValidIPv6Segment()
)验证IPArr
中的每个分段是否都为有效的 IP 分段。 - 如果
IPArr
中的每个分段都为有效的 IP 分段且分段数量合理,则返回对应的 IP 类型,否则返回'Neither'
。
其中最关键的就是第二步和第三步,需要考虑各种有效情况和无效情况,我就是在这里连续遭受了三次毒打:
经过这三次毒打,终于算是通过了提交。相关详解请看下方注释:
/**
* @param {string} IP
* @return {string}
*/
var validIPAddress = function(IP) {
// 如果 IP 中同时存在 . 和 : ,那么一定是无效的 IP 地址,所以直接返回 'Neither'
if(IP.includes('.') && IP.includes(':')) {
return 'Neither';
}
// IPArr用于接收分割出来的 IP 分段
let IPArr = null;
// 如果 IP 中有 . ,那么就按 IPv4 的有效性判断标准来判断其有效性
if(IP.includes('.')) {
IPArr = IP.split('.');
// 注意如果是 IPv4,则其分段数量一定是4
return IPArr.length === 4 && IPArr.every(
cur => isValidIPv4Segment(cur)
) ? 'IPv4' : 'Neither';
}
// 如果 IP 中有 : ,那么就按 IPv6 的有效性判断标准来判断其有效性
IPArr = IP.split(':');
// 注意如果是 IPv6,则其分段数量一定是8
return IPArr.length === 8 && IPArr.every(
cur => isValidIPv6Segment(cur)
) ? 'IPv6' : 'Neither';
// isValidIPv4Segment 用于判断一个字符串是否为有效的 IPv4 分段
function isValidIPv4Segment(seg) {
if(/[a-zA-Z]/.test(seg) || seg.length === 0 || (seg.length > 1 && seg[0] === '0')) {
return false;
}
return 0 <= Number(seg) && Number(seg) <= 255;
}
// isValidIPv6Segment 用于判断一个字符串是否为有效的 IPv6 分段
function isValidIPv6Segment(seg) {
if(/[g-zG-Z]/.test(seg) || seg.length === 0 || seg.length > 4 ) {
return false;
}
return 0 <= parseInt(seg, 16) && parseInt(seg, 16) <= 65535;
}
};
提交记录
73 / 73 个通过测试用例
状态:通过
执行用时:68 ms, 在所有 JavaScript 提交中击败了65.40%的用户
内存消耗:37.7 MB, 在所有 JavaScript 提交中击败了66.35%的用户
时间:2021/10/07 17:21
上面用到了数组对象的 every()
方法,具体可以参考下方MDN文档:
还有一点要注意,那就是 Number()
函数对字符串的转化。当 IP = "1e1.4.5.6"
时,第一个分段为 1e1
。如果用 Number()
函数对其进行转换的话,不会出现预期中的 NaN
,而是 10
:
Number
函数将字符串转为数值,要比parseInt
函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN
。
parseInt('42 cats') // 42
Number('42 cats') // NaN
但是可惜的是,碰上 '1e1'
时,结果好像和我想的不太一样,我目前还没搞清楚原因。
官方题解
更新:2021年7月29日18:43:21
因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。
更新:2021年10月7日17:18:47
【更新结束】
有关参考
更新:2021年10月7日17:18:04
参考:Array.prototype.every() - JavaScript | MDN
参考:Number - JavaScript | MDN
参考:javascript 十六进制数字和字符串相互转换_鸟哥的博客-CSDN博客
参考:数据类型的转换 - JavaScript 教程 - 网道
参考:判断一个字符串是否是16进制_yuyeqianhen的博客-CSDN博客