难度:中等
编写一个函数来验证输入的字符串是否是有效的 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 仅由英文字母,数字,字符 ‘.’ 和 ‘:’ 组成。
解题思路:
考虑所有边界条件即可:
IPv4:
- 地址不能以“.”结尾;
- 段地址数只能为4;
- 段地址只允许长度为[1,3]区间;
- 以0开头时只允许长度为1;
- 段地址只能包含数字;
- 段地址范围为 0 - 255;
IPv6:
- 地址不能以“:”结尾
- 段地址数只能为8;
- 段地址只允许长度为[1,4]区间;
- 段地址每个字符必须是合法的16进制字符;
代码实现:
class Solution {
public String validIPAddress(String IP) {
if (IP.indexOf(".") != -1) {
return validateIPv4(IP);
}
if (IP.indexOf(":") != -1) {
return validateIPv6(IP);
}
return "Neither";
}
/**
* IPv4校验
* @param IP IP地址
* @return 校验结果
*/
public String validateIPv4(String IP) {
//地址不能以“.”结尾
if(IP.endsWith(".")) return "Neither";
String[] ipv4 = IP.split("\\.");
//段地址数只能为4;
if (ipv4.length != 4) return "Neither";
for (String s : ipv4) {
//段地址只允许长度为[1,3]区间;
if (s.length() == 0 || s.length() > 3) return "Neither";
//以0开头时只允许长度为1;
if (s.charAt(0) == '0' && s.length() > 1) return "Neither";
//段地址只能包含数字;
if (!isNumeric(s)) return "Neither";
//段地址范围为 0 - 255
if (Integer.parseInt(s) > 255) return "Neither";
}
return "IPv4";
}
/**
* IPv6校验
* @param IP IP地址
* @return 校验结果
*/
public String validateIPv6(String IP) {
//地址不能以“:”结尾
if(IP.endsWith(":")) return "Neither";
String[] ipv6 = IP.split(":");
//段地址数只能为8;
if (ipv6.length != 8) return "Neither";
for (String s : ipv6) {
//段地址只允许长度为[1,4]区间;
if (s.length() == 0 || s.length() > 4) return "Neither";
//段地址每个字符必须是合法的16进制字符
if (!isHex(s)) return "Neither";
}
return "IPv6";
}
/**
* 判断字符串是否是数字串
* @param str 字符串
* @return 判断结果
*/
public static boolean isNumeric(String str){
for (char c : str.toCharArray()){
if (!Character.isDigit(c)) return false;
}
return true;
}
/**
* 判断字符串是否是有效的十六进制字符串
* @param str 字符串
* @return 判断结果
*/
public static boolean isHex(String str){
final String number = "0123456789abcedfABCDEF";
for (char c : str.toCharArray()){
if(number.indexOf(c) == -1) return false;
}
return true;
}
}
复杂度分析
- 时间复杂度:O(1)。
- 空间复杂度:O(1)。