在问 · 算法题解

468. 验证IP地址

中等字符串分割字符串逐段校验力扣原题 ↗

题目描述

输入字符串 queryIP,判断它是哪一类地址:合法 IPv4 返回 "IPv4",合法 IPv6 返回 "IPv6",都不是则返回 "Neither"。

合法 IPv4 由 4 段组成,段之间用 . 连接。每段是 0 到 255 的十进制整数,不能为空,也不能有多余的前导零(单独的 0 可以,01、00 不行),只能含数字。

合法 IPv6 由 8 段组成,段之间用 : 连接。每段长 1 到 4 个字符,字符只能是数字或 a-f、A-F。IPv6 的段允许前导零,但不能为空,也不能超过 4 个字符。

示例 1
输入:queryIP = "172.16.254.1"
输出:"IPv4"

解释:四段都在 0 到 255 之间且无前导零。

示例 2
输入:queryIP = "2001:0db8:85a3:0:0:8A2E:0370:7334"
输出:"IPv6"

解释:八段都是 1 到 4 位的十六进制串。

示例 3
输入:queryIP = "256.256.256.256"
输出:"Neither"

解释:每段都超过 255,也不是 IPv6 格式。

数据范围

  • queryIP 只包含英文字母、数字以及字符 '.' 和 ':'。

解题思路:分割字符串逐段校验

先按分隔符个数分类:恰好 3 个 . 就按 IPv4 检查,恰好 7 个 : 就按 IPv6 检查,其他一律 Neither。IPv4 每段:非空、最多 3 位、全是数字、无前导零、不超过 255。IPv6 每段:长度 1–4、全是十六进制字符。任一段不合法立即返回 Neither。

为什么正确

当前段之前的所有段都已通过全部规则。

复杂度分析

时间 O(n);空间 O(n)(分割结果)。

易错点

空段(如 "1.0.1.")很容易被 split 忽略:Java 的 split 默认会丢掉末尾空串,要传 -1。前导零只对 IPv4 非法,IPv6 允许。还要先限制长度再转整数,避免超长数字溢出。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def validIPAddress(self, queryIP: str) -> str:
        if queryIP.count('.') == 3:
            for p in queryIP.split('.'):
                if not p or len(p) > 3 or not p.isdigit():
                    return 'Neither'
                if (p[0] == '0' and len(p) > 1) or int(p) > 255:
                    return 'Neither'
            return 'IPv4'
        if queryIP.count(':') == 7:
            for p in queryIP.split(':'):
                if not 1 <= len(p) <= 4 or any(c not in '0123456789abcdefABCDEF' for c in p):
                    return 'Neither'
            return 'IPv6'
        return 'Neither'

载入编辑器,自己跑一遍 →

其他解法

逐段校验每条规则都清楚可见;正则把规则压缩成两个模式,简洁但可读性差。

解法 2:正则表达式 时间 O(n),空间 O(1)

把规则写成正则:IPv4 每段为 25[0-5]、2[0-4]x、1xx 或 [1-9]?x,可排除前导零和超过 255 的数,共 4 段用点连接。IPv6 为 8 组 1~4 位十六进制数,用冒号连接。先尝试整串匹配 IPv4,再匹配 IPv6,都不匹配就返回 Neither。

规则集中在一处,代码最短。正则不易读,难以调试,也不容易给出具体的错误位置。

import re


class Solution:
    # 每段 0~255 且无前导零:25[0-5] | 2[0-4]x | 1xx | [1-9]?x
    IPV4 = re.compile(r'((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])')
    # 8 组 1~4 位十六进制数
    IPV6 = re.compile(r'([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}')

    def validIPAddress(self, queryIP: str) -> str:
        if self.IPV4.fullmatch(queryIP):
            return 'IPv4'
        if self.IPV6.fullmatch(queryIP):
            return 'IPv6'
        return 'Neither'

字符串 专题的其他题目

查看 字符串 全部题目 →