文章目录
- 摘要
- 描述
- IPv4 的规则可以总结成一句话
- IPv6 的规则则是
- 题解答案
- 题解代码分析
- IPv4 校验逻辑拆解
- IPv6 校验逻辑拆解
- 示例测试及结果
- 示例 1
- 示例 2
- 示例 3
- 时间复杂度
- 空间复杂度
- 总结
摘要
《验证 IP 地址》是一道非常工程化的题。
它不像很多算法题那样考复杂技巧,而是更像我们在写后台接口、网关校验、日志解析时,经常会遇到的那种“脏数据判断”问题。
这道题的核心不在算法,而在于三点:
- 规则是否吃透
- 边界是否考虑完整
- 代码是否足够清晰、可维护
如果你平时写过参数校验、输入校验,这道题会让你有一种“这不就是我每天在干的事吗”的熟悉感。
描述
题目给你一个字符串queryIP,要求判断它属于哪一种类型:
- 合法的 IPv4 → 返回
"IPv4" - 合法的 IPv6 → 返回
"IPv6" - 两者都不是 → 返回
"Neither"
IPv4 的规则可以总结成一句话
x1.x2.x3.x4- 必须正好 4 段
- 每段是 0~255 的十进制数字
- 不能有前导零
- 只能是数字,不能夹杂奇怪字符
IPv6 的规则则是
x1:x2:x3:x4:x5:x6:x7:x8- 必须正好 8 段
- 每段 1~4 位
- 只能是十六进制字符(0-9, a-f, A-F)
- 允许前导零
- 不支持
::这种缩写(这是本题特别容易踩的坑)
题解答案
整体解法非常直接,也非常“工程化”:
先看分隔符
- 包含
.→ 尝试按 IPv4 规则解析 - 包含
:→ 尝试按 IPv6 规则解析
- 包含
严格按规则逐段校验
任何一条不满足,直接判
Neither
核心原则只有一个:
宁可判错为非法,也不能放过一个非法输入。
题解代码分析
下面是完整的 Swift 实现,结构清晰,逻辑拆分明确,可以直接运行。
classSolution{funcvalidIPAddress(_queryIP:String)->String{ifqueryIP.contains("."){returnisValidIPv4(queryIP)?"IPv4":"Neither"}ifqueryIP.contains(":"){returnisValidIPv6(queryIP)?"IPv6":"Neither"}return"Neither"}privatefuncisValidIPv4(_ip:String)->Bool{letparts=ip.split(separator:".",omittingEmptySubsequences:false)ifparts.count!=4{returnfalse}forpartinparts{// 不能为空ifpart.isEmpty{returnfalse}// 不能有前导零ifpart.count>1&&part.first=="0"{returnfalse}// 必须全是数字guardletnum=Int(part),num>=0&&num<=255else{returnfalse}}returntrue}privatefuncisValidIPv6(_ip:String)->Bool{letparts=ip.split(separator:":",omittingEmptySubsequences:false)ifparts.count!=8{returnfalse}forpartinparts{// 长度 1~4ifpart.isEmpty||part.count>4{returnfalse}forchinpart{if!ch.isHexDigit{returnfalse}}}returntrue}}IPv4 校验逻辑拆解
letparts=ip.split(separator:".",omittingEmptySubsequences:false)这里非常关键的一点是:
不能省略空字符串
否则像下面这种:
"192..168.1"会被错误拆成 3 段。
ifpart.count>1&&part.first=="0"这一步是专门防:
"01""001"
这是 IPv4 非常典型的坑点。
IPv6 校验逻辑拆解
IPv6 这边反而规则更“干净”:
- 段数必须 8
- 每段最多 4 位
- 每个字符必须是十六进制
Swift 的这个 API 在这里非常好用:
ch.isHexDigit可读性和安全性都比手写判断强。
示例测试及结果
示例 1
letsolution=Solution()print(solution.validIPAddress("172.16.254.1"))输出:
IPv4原因很简单:
4 段、范围合法、无前导零。
示例 2
print(solution.validIPAddress("2001:0db8:85a3:0:0:8A2E:0370:7334"))输出:
IPv6大小写混用、前导零,全都允许。
示例 3
print(solution.validIPAddress("256.256.256.256"))输出:
Neither单段数值超出 255,直接判非法。
时间复杂度
- IPv4:最多检查 4 段
- IPv6:最多检查 8 段,每段 4 个字符
整体时间复杂度:
O(n)其中n是字符串长度,实际上非常小。
空间复杂度
只使用了拆分后的数组和少量变量:
O(1)总结
《验证 IP 地址》这道题,非常不像“刷题”,但非常像“真实工作”。
它真正考察的是:
- 你能不能严格遵守规则
- 你会不会遗漏边界
- 你的代码是否清晰、可维护、可扩展