「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」
1、题目
编写一个函数来验证输入的字符串是否是有效的 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仅由英文字母,数字,字符'.'和':'组成。
2、思路
(字符串 + 模拟)
一个合法的IPv4满足以下条件:
- 被
.分割成4组字符串。 - 每组字符串不为空,且长度
<= 3。 - 每组字符串转换成数字后介于
0 ~ 255之间。 - 每组字符串仅由数字字符组成。
- 每组字符串的长度大于
1时,不包含前导0。
一个合法的IPv6满足以下条件:
- 被
:分割成8组字符串。 - 每组字符串不为空,且长度
<= 4。 - 每组字符串转化成数字后为一个16进制数,即字符范围为:
0~9,a~f,A~F。
由于C++中没有按字符分割的函数,因此我们自定义一个分割函数split,如下:
vector<string> split(string ip, char t) {
vector<string> items;
for (int i = 0; i < ip.size(); i ++ ) {
int j = i;
string item;
while (ip[j] != t) item += ip[j ++ ];
i = j;
items.push_back(item);
}
return items;
}
这里使用了双指针算法,传入一个要分割的字符串ip和分割字符t,最后返回分割好的字符串数组items。
判断一个合法的IPv4和IPv6,我们首先调用分割函数split,然后按照上述条件模拟即可。
具体过程如下:
- 1、如果一个字符串
ip即包含.也包含:,我们直接返回Neither。 - 2、如果包含
.,我们进行check_ipv4(ip),IPv4的合法性判断。 - 3、如果包含
:,我们进行check_ipv6(ip),IPv6的合法性判断。
时间复杂度分析: 每个字符串仅会被遍历一遍,因此时间复杂度为O(n)。
3、c++代码
class Solution {
public:
vector<string> split(string ip, char t){
vector<string> items;
for(int i = 0; i < ip.size(); i++){
int j = i;
string item;
while(j < ip.size() && ip[j] != t) item += ip[j++];
i = j;
items.push_back(item);
}
return items;
}
string check_ipv4(string ip){
auto items = split(ip + '.', '.');a
if(items.size() != 4) return "Neither";
for(string item : items){
if(item.empty() || item.size() > 3) return "Neither";
if(item.size() > 1 && item[0] == '0') return "Neither";
for(char c : item){
if(c < '0' || c > '9') return "Neither";
}
int t = stoi(item);
if(t > 255) return "Neither";
}
return "IPv4";
}
bool check(char c){
if (c >= '0' && c <= '9') return true;
if (c >= 'a' && c <= 'f') return true;
if (c >= 'A' && c <= 'F') return true;
return false;
}
string check_ipv6(string ip){
auto items = split(ip + ':', ':');
if(items.size() != 8) return "Neither";
for(string item : items){
if(item.empty() || item.size() > 4) return "Neither";
for(char c : item){
if(!check(c)) return "Neither";
}
}
return "IPv6";
}
string validIPAddress(string ip) {
if(ip.find('.') != -1 && ip.find(':') != -1) return "Neither";
if(ip.find('.') != -1) return check_ipv4(ip);
if(ip.find(':') != -1) return check_ipv6(ip);
return "Neither";
}
};
4、Java代码
class Solution {
public String validIPAddress(String IP) {
if (IP == null || IP.length() == 0) return "Neither";
if (isIPv4(IP)) return "IPv4";
if (isIPv6(IP)) return "IPv6";
return "Neither";
}
public boolean isIPv4(String IP){
String[] ips = IP.split("\\.");
if (ips.length != 4) return false;
if (IP.charAt(0) == '.' || IP.charAt(IP.length()-1) == '.') return false;
for (int i = 0 ; i < ips.length ; i ++)
if (!isIPv4Group(ips[i])) return false;
return true;
}
private boolean isIPv4Group(String IPG){
if (IPG == null || IPG.length() == 0 || IPG.length() > 3) return false;
for (int i = 0 ; i < IPG.length(); i++)
if (!('0' <= IPG.charAt(i) && IPG.charAt(i) <= '9')) return false;
int x = Integer.valueOf(IPG);
if (x< 0 || x > 255 || (IPG.charAt(0) == '0' && IPG.length() > 1))
return false;
return true;
}
public boolean isIPv6(String IP){
String[] ips = IP.split(":");
if (ips.length != 8) return false;
if (IP.charAt(0) == ':' || IP.charAt(IP.length()-1) == ':') return false;
for (int i = 0 ; i < ips.length ; i ++){
if (!isIPv6Group(ips[i])) return false;
}
return true;
}
private boolean isIPv6Group(String IPG){
if (IPG == null || IPG.length() == 0 || IPG.length() > 4) return false;
for (int i = 0 ; i < IPG.length(); i++)
if (!('0' <= IPG.charAt(i) && IPG.charAt(i) <= '9' || 'a' <= IPG.charAt(i) && IPG.charAt(i) <= 'f' || 'A' <= IPG.charAt(i) && IPG.charAt(i) <='F'))
return false;
return true;
}
}