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'

所有这种字符串处理的题目,基础和细节才是最重要的,有的题目看似很简单,但是有很多细节和条件,需要一一去分析,所以做这种题目需要有足够的细心和耐心(我的功力还不够,还需要继续练习)。

posted @ 2022-05-29 12:42  *小白*  阅读(240)  评论(0)    收藏  举报