LeetCode题练习与总结:验证 IP 地址--468

一、题目描述

给定一个字符串 queryIP。如果是有效的 IPv4 地址,返回 "IPv4" ;如果是有效的 IPv6 地址,返回 "IPv6" ;如果不是上述类型的 IP 地址,返回 "Neither"

有效的IPv4地址"x1.x2.x3.x4" 形式的IP地址。 其中 0 <= xi <= 255xi 不能包含 前导零。例如: "192.168.1.1""192.168.1.0" 为有效IPv4地址, "192.168.01.1" 为无效IPv4地址; "192.168.1.00""[email protected]" 为无效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 地址。

示例 1:

复制代码
输入:queryIP = "172.16.254.1"
输出:"IPv4"
解释:有效的 IPv4 地址,返回 "IPv4"

示例 2:

复制代码
输入:queryIP = "2001:0db8:85a3:0:0:8A2E:0370:7334"
输出:"IPv6"
解释:有效的 IPv6 地址,返回 "IPv6"

示例 3:

复制代码
输入:queryIP = "256.256.256.256"
输出:"Neither"
解释:既不是 IPv4 地址,又不是 IPv6 地址

提示:

  • queryIP 仅由英文字母,数字,字符 '.'':' 组成。

二、解题思路

  • 首先,我们可以通过检查字符串中是否包含字符 '.' 或 ':' 来判断它是 IPv4 还是 IPv6 地址。
  • 对于 IPv4 地址:
    • 使用 '.' 分割字符串,检查分割后的数组长度是否为 4。
    • 对于每个分割后的字符串,检查是否在 0 到 255 之间,且没有前导零(除非字符串就是 "0")。
  • 对于 IPv6 地址:
    • 使用 ':' 分割字符串,检查分割后的数组长度是否为 8。
    • 对于每个分割后的字符串,检查长度是否在 1 到 4 之间,且只包含十六进制字符。
  • 如果都不满足,则返回 "Neither"。

三、具体代码

java 复制代码
class Solution {
    public String validIPAddress(String queryIP) {
        if (queryIP.contains(".")) {
            return validateIPv4(queryIP) ? "IPv4" : "Neither";
        } else if (queryIP.contains(":")) {
            return validateIPv6(queryIP) ? "IPv6" : "Neither";
        } else {
            return "Neither";
        }
    }

    private boolean validateIPv4(String ip) {
        String[] parts = ip.split("\\.", -1);
        if (parts.length != 4) return false;
        for (String part : parts) {
            if (!part.matches("0|[1-9][0-9]{0,2}")) return false;
            if (part.length() > 1 && part.startsWith("0")) return false;
            if (Integer.parseInt(part) > 255) return false;
        }
        return true;
    }

    private boolean validateIPv6(String ip) {
        String[] parts = ip.split(":", -1);
        if (parts.length != 8) return false;
        for (String part : parts) {
            if (!part.matches("[0-9a-fA-F]{1,4}")) return false;
        }
        return true;
    }
}

在这段代码中,我们使用了正则表达式来验证 IPv4 和 IPv6 地址的各个部分。对于 IPv4,我们检查每个部分是否是 0 到 255 之间的数字,且没有前导零(除非部分是 "0")。对于 IPv6,我们检查每个部分是否只包含 1 到 4 个十六进制字符。

四、时间复杂度和空间复杂度

1. 时间复杂度
  • validateIPv4 方法

    • split("\\.", -1):这个操作会遍历整个字符串 queryIP 一次,所以时间复杂度是 O(n),其中 n 是 queryIP 的长度。
    • parts.length != 4:这是一个常数时间操作,时间复杂度是 O(1)。
    • 循环遍历 parts 数组:这个循环会执行 4 次(因为有效的 IPv4 地址有 4 个部分),所以时间复杂度是 O(1)。
      • part.matches("0|[1-9][0-9]{0,2}"):这是一个正则表达式匹配操作,时间复杂度取决于正则表达式的复杂度,但由于正则表达式固定且简单,可以认为它是 O(1)。
      • part.startsWith("0"):这是一个常数时间操作,时间复杂度是 O(1)。
      • Integer.parseInt(part) > 255:这是一个常数时间操作,时间复杂度是 O(1)。
    • 综合以上,validateIPv4 方法的时间复杂度是 O(n)。
  • validateIPv6 方法

    • split(":", -1):这个操作会遍历整个字符串 queryIP 一次,所以时间复杂度是 O(n),其中 n 是 queryIP 的长度。
    • parts.length != 8:这是一个常数时间操作,时间复杂度是 O(1)。
    • 循环遍历 parts 数组:这个循环会执行 8 次(因为有效的 IPv6 地址有 8 个部分),所以时间复杂度是 O(1)。
      • part.matches("[0-9a-fA-F]{1,4}"):这是一个正则表达式匹配操作,时间复杂度同样是 O(1)。
    • 综合以上,validateIPv6 方法的时间复杂度也是 O(n)。
2. 空间复杂度
  • validateIPv4 方法

    • parts 数组:这个数组固定有 4 个元素,所以空间复杂度是 O(1)。
  • validateIPv6 方法

    • parts 数组:这个数组固定有 8 个元素,所以空间复杂度是 O(1)。

综上所述,整体的时间复杂度是 O(n),空间复杂度是 O(1)。这里的空间复杂度只考虑了额外的空间使用,没有考虑输入字符串 queryIP 本身占用的空间。

五、总结知识点

  • 字符串操作

    • contains(String str): 检查字符串是否包含指定的子字符串。
    • split(String regex, int limit): 根据匹配给定的正则表达式来拆分字符串,并限定拆分次数。
  • 正则表达式

    • matches(String regex): 告知这个字符串是否匹配给定的正则表达式。
    • 正则表达式的基本用法,如字符类(. 表示任意字符,[0-9] 表示数字,[a-fA-F] 表示十六进制字符)和量词({0,2} 表示匹配前面的字符 0 到 2 次)。
  • 条件判断

    • if-else 语句:用于根据条件执行不同的代码块。
  • 字符串与整数的转换

    • Integer.parseInt(String s): 将字符串参数解析为带符号的整数。
  • 字符串方法

    • startsWith(String prefix): 检查字符串是否以指定的前缀开始。
  • 数组操作

    • 数组的声明和使用。
    • 使用增强型 for 循环遍历数组。
  • 方法重载

    • 在同一个类中定义了两个同名的 validateIPvX 方法,但参数类型不同,这是方法重载的一个例子。
  • 返回值

    • 方法返回布尔值以表示条件是否满足。
    • 方法返回字符串以表示 IP 地址的类型。
  • 面向对象编程

    • 使用私有方法 validateIPv4validateIPv6 来封装验证逻辑,体现了封装的原则。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

相关推荐
TDengine (老段)8 分钟前
TDengine 开发指南—— UDF函数
java·大数据·数据库·物联网·数据分析·tdengine·涛思数据
键盘林11 分钟前
分布式系统简述
java·开发语言
可儿·四系桜12 分钟前
如何在 Java 中优雅地使用 Redisson 实现分布式锁
java·开发语言·分布式
sszdzq27 分钟前
SpringCloudGateway 自定义局部过滤器
java·spring boot
消失的旧时光-194334 分钟前
Android 开发中配置 USB 配件模式(Accessory Mode) 配件过滤器的配置
android·java
IDRSolutions_CN41 分钟前
如何在网页里填写 PDF 表格?
java·经验分享·pdf·软件工程·团队开发
-兰天白云-1 小时前
java转pdf工具对比
java
全干engineer1 小时前
web3-基于贝尔曼福特算法(Bellman-Ford )与 SMT 的 Web3 DeFi 套利策略研究
算法·金融·web3·去中心化·区块链·智能合约
BillKu1 小时前
Java中List的forEach用法详解
java·windows·list