题目描述
给定一个字符串 queryIP。如果是有效的 IPv4 地址,返回 “IPv4” ;如果是有效的 IPv6 地址,返回 “IPv6” ;如果不是上述类型的 IP 地址,返回 “Neither” 。
有效的IPv4地址 是 “x1.x2.x3.x4” 形式的IP地址。 其中 0 <= xi <= 255 且 xi 不能包含 前导零。例如: “192.168.1.1” 、 “192.168.1.0” 为有效IPv4地址, “192.168.01.1” 为无效IPv4地址; “192.168.1.00” 、 “192.168@1.1” 为无效IPv4地址。
一个有效的IPv6地址 是一个格式为“x1:x2:x3:x4:x5:x6:x7:x8” 的IP地址,其中:
- 1 <= xi.length <= 4
- xi 是一个 十六进制字符串 ,可以包含数字、小写英文字母( ‘a’ 到 ‘f’ )和大写英文字母( ‘A’ 到 ‘F’ )。
- 在 xi 中允许前导零。
例如 “2001:0db8:85a3:0000:0000:8a2e:0370:7334” 和 “2001:db8:85a3:0:0:8A2E:0370:7334” 是有效的 IPv6 地址,而 “2001:0db8:85a3::8A2E:037j:7334” 和 “02001:0db8:85a3:0000:0000:8a2e:0370:7334” 是无效的 IPv6 地址。
简化题目
IPv4规则:
- 按’.'分割字符串后需要长度为4;
- 分割的每个字符串长度在1到3之间;
- 可以解析为数字;
- 不含前导零然后大小在0到255之间;
IPv6规则:
- 按’:'分割字符串后需要长度为8;
- 且分割的每个字符串长度在1到4之间;
- 每个字符都需要在0-9或a-f或A-F中;
思路分析
按照上面的规则一步一步写就可以了。
可以模拟,可以正则。
法一(模拟):
模拟法代码写的比较多,但是很好懂。
完整代码
class Solution:
def validIPAddress(self, queryIP: str) -> str:
for i in queryIP:
if i == '.':
# IPV4
res = queryIP.split('.')
if len(res) != 4: # 分割后长度需为4.
return "Neither"
for j in res:
if not j.isdigit(): # 判断是否只有数字
return "Neither"
if int(j) < 0 or int(j) > 255: # 每个字符大小需要在 0~255之间
return "Neither"
if len(j)<1 or len(j)>3: # 每个字符长度需要在 1~3之间
return "Neither"
if j[0] == '0': # 若有前导0 则必须是只有一个0,00都不行
if len(j) > 1:
return "Neither"
return "IPv4"
elif i == ':':
# IPV6
res = queryIP.split(":")
if len(res) != 8: # IPv6 长度为8
return "Neither"
for k in res:
if len(k) < 1 or len(k) > 4: # 每个字符长度为1~4
return "Neither"
temp = "0123456789abcdefABCDEF" # ipv6可能的字符
for p in k: # 每个字符看是不是在0~9 a~f A~F
if p not in temp:
return "Neither"
return "IPv6"
return "Neither"
法二(正则):
正则实际上不是整体去正则,那样比较容易出错还很乱,我是先分割了一下,然后再对每一个小块进行正则。
有一个比较容易出错地方在判断IPv4的时候,不允许前导0,ipv4的每一个小段里最多3个字符,所以是[1-9]先确定第一个字符不是0。那就还剩下最多2个字符,所以\d{0,2}。
完整代码
class Solution:
def validIPAddress(self, queryIP: str) -> str:
import re
ipv4 = queryIP.split(".")
ipv6 = queryIP.split(":")
if len(ipv4) == 4:
for i in ipv4:
if not (re.match('^0$|(^[1-9]\d{0,2}$)',i) and int(i) < 256):
return "Neither"
return 'IPv4'
elif len(ipv6) == 8:
for j in ipv6:
if not re.match('^[0-9a-fA-F]{1,4}$',j):
return "Neither"
return 'IPv6'
return "Neither"