LeetCode-468. 验证IP地址
468. 验证IP地址
给定一个字符串 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 地址。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/validate-ip-address
一看题目就是字符串处理的类型,对于这种类型的题目一般用到的方法是字符串的分割、替换、判断数字英文、进制转换,或者转化为ascii码求值。
这种典型的字符串模拟题目没有套路可言,唯一能做得就是:掌握常用的字符串操作及其变种;细心逐字逐句的阅读题目,确保不漏掉任何一处细节。
很多时候我做这种题目都以为很简单,一眼就能看明白题目要求做什么,于是没有仔细阅读就开始写答案。
但是往往写出来得答案只能通过示例或者一小部分测试用例,然后根据出错的用例不断的添加删除判断语句,结果是做了很久还是没有通过。
究其原因有以下几点:
1.没有认真阅读题目,往往只是大致扫一遍就开始做,导致忽略了其中关键的细节
2.根据题目给的示例写答案,有的时候题目给的示例具有很强的误导性,会导致我考虑情况不全,所以经常出现的结果是这个用例通过了,下个用例没通过,然后无止境的修改代码。
3.基础不够牢靠,有的字符处理写不出来,如转换ascii码求值(不是不知道这个方法,是有的语句处理不太熟练)导致经常卡在一个地方需要用其他的方式去处理,很影响整体的代码思考。
这道题阅读分析题意可以知道以下几点:
1.给出一个字符串让我们判断其是否是合法的ipv4或ipv6,所以我们要分为两种情况去判断
2.如果给出的字符串符合ipv4的特点(这里我判断符号'.'是否在给定的字符串里判断,因为给的字符串要么包含'.',要么包含':',不会出现两种字符同时包含的情况,所以可以这样判断)
接下来就是仔细阅读符合ipv4的条件是什么
(1)有效的IPv4地址 是 “x1.x2.x3.x4” 形式的IP地址 --意思是说只包含4组,可以通过分割'.'后判断数组长度等于4或者判断'.'在字符串中总数为3,这里我用的是前面这种方法
(2)其中 0 <= xi <= 255 且 xi 不能包含 前导零
分析可得:
其中 0 <= xi <= 255 -- 每组xi必定是数字,且满足0 <= xi <= 255 ,这里需要做两个操作,一个是判断字符串是否是纯数字,一个是转换每组字符串为数字后判断是否在指定区间
xi 不能包含 前导零 -- 这里我通过判断每组字符串的长度大于1时,它的首位不能为0来解决
于是有了下面的代码
if '.' in queryIP: ret = queryIP.split('.') if len(ret) != 4: return 'Neither' for i in ret: if not i.isdigit() or (len(i) > 1 and i[0] == '0') or (int(i) < 0 or int(i) > 255): return 'Neither' return 'IPv4'
3.接下来需要判断给定的字符串是否符合ipv6的特点,判断方法与判断ipv4的方法一致,只是条件不一样而已
接下来同样的分析符合ipv6的条件是什么
(1)一个有效的IPv6地址 是一个格式为“x1:x2:x3:x4:x5:x6:x7:x8” 的IP地址 --分割后的数组长度为8
(2)1 <= xi.length <= 4 -- 每组xi的长度在1到4之间
(3)xi 是一个 十六进制字符串 ,可以包含数字、小写英文字母( 'a' 到 'f' )和大写英文字母( 'A' 到 'F' )。--意思是xi中可能包含数字和大小写的a-f(刚开始没仔细看题目,导致以为是可以包含数字、英文大小写,所以看似简单的题目细节才是最重要的)
(4)在 xi 中允许前导零。--那我就可以不用去判断是否有前导零,因为不管它首位是什么只要符合条件(3)就可以了。
于是有了下面这段代码
elif ':' in queryIP: tmp = 'abcdefABCDEF' ret = queryIP.split(':') if len(ret) != 8: return 'Neither' for i in ret: if len(i) < 1 or len(i) > 4: return 'Neither' for j in range(len(i)): if not i[j].isdigit() and i[j] not in tmp: return 'Neither' return 'IPv6'
4.如果给出的字符串既不符合ipv4的特点又不符合ipv6的特点,则返回Neither
综上,完整的代码如下:
class Solution: def validIPAddress(self, queryIP: str) -> str: if '.' in queryIP: ret = queryIP.split('.') if len(ret) != 4: return 'Neither' for i in ret: if not i.isdigit() or (len(i) > 1 and i[0] == '0') or (int(i) < 0 or int(i) > 255): return 'Neither' return 'IPv4' elif ':' in queryIP: tmp = 'abcdefABCDEF' ret = queryIP.split(':') if len(ret) != 8: return 'Neither' for i in ret: if len(i) < 1 or len(i) > 4: return 'Neither' for j in range(len(i)): if not i[j].isdigit() and i[j] not in tmp: return 'Neither' return 'IPv6' else: return 'Neither'
所有这种字符串处理的题目,基础和细节才是最重要的,有的题目看似很简单,但是有很多细节和条件,需要一一去分析,所以做这种题目需要有足够的细心和耐心(我的功力还不够,还需要继续练习)。

浙公网安备 33010602011771号