LeetCode热题(JS版) - 468. 验证IP地址

174 阅读2分钟

题目描述

编写一个函数来验证输入的字符串是否是有效的 IPv4 或 IPv6 地址。

  • 如果是有效的 IPv4 地址,返回 "IPv4" ;
  • 如果是有效的 IPv6 地址,返回 "IPv6" ;
  • 如果不是上述类型的 IP 地址,返回 "Neither" 。
IPv4 地址由十进制数和点来表示,每个地址包含四个十进制数,其范围为 0 - 255,用(".")分割。
比如,172.16.254.1; 
同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。 

IPv6 地址由 816 进制的数字来表示,每组表示 16 比特。这些组数字通过 (":")分割。
比如,2001:0db8:85a3:0000:0000:8a2e:0370:7334 是一个有效的地址。
而且,我们可以加入一些以 0 开头的数字,字母可以使用大写,也可以使用小写。
所以, 2001:db8:85a3:0:0:8A2E:0370:7334 也是一个有效的 IPv6 表示法(即,忽略前导 0)。

示例:

输入:IP = "172.16.254.1"
输出:"IPv4"
解释:有效的 IPv4 地址,返回 "IPv4"

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

解题思路

分别判断输入字符串是否是 IPv4 或 IPv6 即可。

对于 IPv4 来说,需要先判断字符串中 "." 的个数是否为 3,然后将字符串用 "." 分割成 4 个子字符串(即四段 IP 地址),再判断每一段是否合法(大于等于 0 小于等于 255 且没有前导零)。

对于 IPv6 来说,需要先判断字符串中 ":" 的个数是否为 7,然后将字符串用 ":" 分割成 8 个子字符串(即八段 IP 地址),再判断每一段是否合法(只包含数字和字母,长度不超过 4)。

注意:在判断 IPv6 段的合法性时,需要转换为小写字母再进行判断。

代码实现

function validIPAddress(IP: string): string {    
    if (IP.indexOf('.') !== -1 && isValidIPv4(IP)) {
        return 'IPv4';
    } else if (IP.indexOf(':') !== -1 && isValidIPv6(IP)) {
        return 'IPv6';
    } else {
        return 'Neither';
    }
}

function isValidIPv4(ip: string): boolean {
    const nums = ip.split('.');
    if (nums.length !== 4) return false;
    
    for (const num of nums) {
        if (num === '' || num.length > 1 && num[0] === '0') return false; // 长度大于 1 且第一位是 0 的不合法
        
        const n = Number(num);
        if (isNaN(n) || n < 0 || n > 255) return false;
    }
    return true;
}

function isValidIPv6(ip: string): boolean {
    const nums = ip.split(':');
    if (nums.length !== 8) return false;
    
    for (const num of nums) {
        if (num === '' || num.length > 4) return false;
        
        for (const ch of num) {
            if (!/[0-9a-fA-F]/.test(ch)) return false;
        }
    }
    return true;
}

时间和空间复杂度

  • 时间复杂度:O(n)\mathcal{O}(n),其中 nn 为输入字符串的长度。

  • 空间复杂度:O(1)\mathcal{O}(1)