0
点赞
收藏
分享

微信扫一扫

468. 验证IP地址 : 简单字符串模拟题

题目描述

这是 LeetCode 上的 ​​468. 验证IP地址 ,难度为 中等

Tag : 「模拟」、「双指针」

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

有效的 ​​IPv4​​​ 地址 是 ​​“x1.x2.x3.x4”​​​ 形式的 ​​IP​​​ 地址。 其中468. 验证IP地址 : 简单字符串模拟题_后端 且 468. 验证IP地址 : 简单字符串模拟题_双指针_02 不能包含 前导零。

例如: ​​“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​​ 地址,其中:

  • 468. 验证IP地址 : 简单字符串模拟题_双指针_03
  • 468. 验证IP地址 : 简单字符串模拟题_双指针_02是一个 十六进制字符串 ,可以包含数字、小写英文字母(​​​'a'​​​ 到​​'f'​​​ )和大写英文字母(​​'A'​​​ 到​​'F'​​ )。
  • 468. 验证IP地址 : 简单字符串模拟题_双指针_02中允许前导零。

例如 ​​"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​​​ 中由 ​​.​​​/​​:​​​ 分割的部分称为 ​​item​​。

无论是 ​​IPv4​​​ 还是 ​​IPv6​​​,我们都只需将连续段的 ​​item​​​ 取出,并结合题意判断即可,一个较为简单的方式使用 ​​split​​​ 操作来得到所有的 ​​item​​​,考虑到某些语言并不内置 ​​split​​,这里采取双指针的方式来做。

为方便大家理解,今天将题解文字说明写到注释中。

代码:

class Solution {
public String validIPAddress(String ip) {
if (ip.indexOf(".") >= 0 && check4(ip)) return "IPv4";
if (ip.indexOf(":") >= 0 && check6(ip)) return "IPv6";
return "Neither";
}
boolean check4(String ip) {
int n = ip.length(), cnt = 0;
char[] cs = ip.toCharArray();
for (int i = 0; i < n && cnt <= 3; ) {
// 找到连续数字段,以 x 存取
int j = i, x = 0;
while (j < n && cs[j] >= '0' && cs[j] <= '9' && x <= 255) x = x * 10 + (cs[j++] - '0');
// 非 item 字符之间没有 item
if (i == j) return false;
// 含前导零 或 数值大于 255
if ((j - i > 1 && cs[i] == '0') || (x > 255)) return false;
i = j + 1;
if (j == n) continue;
// 存在除 . 以外的其他非数字字符
if (cs[j] != '.') return false;
cnt++;
}
// 恰好存在 3 个不位于两端的 .
return cnt == 3 && cs[0] != '.' && cs[n - 1] != '.';
}
boolean check6(String ip) {
int n = ip.length(), cnt = 0;
char[] cs = ip.toCharArray();
for (int i = 0; i < n && cnt <= 7; ) {
int j = i;
while (j < n && ((cs[j] >= 'a' && cs[j] <= 'f') || (cs[j] >= 'A' && cs[j] <= 'F') || (cs[j] >= '0' && cs[j] <= '9'))) j++;
// 非 item 字符之间没有 item 或 长度超过 4
if (i == j || j - i > 4) return false;
i = j + 1;
if (j == n) continue;
// 存在除 : 以外的其他非数字字符
if (cs[j] != ':') return false;
cnt++;
}
// 恰好存在 7 个不位于两段的 :
return cnt == 7 && cs[0] != ':' && cs[n - 1] != ':';
}
}
  • 时间复杂度:468. 验证IP地址 : 简单字符串模拟题_算法_06
  • 空间复杂度:使用​​toCharArray​​​ 操作会产生新数组,复杂度为468. 验证IP地址 : 简单字符串模拟题_算法_06,使用​​​charAt​​​ 操作代替复杂度为468. 验证IP地址 : 简单字符串模拟题_后端_08

最后

这是我们「刷穿 LeetCode」系列文章的第 ​​No.468​​ 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour… 。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

举报

相关推荐

0 条评论