题目链接

LeetCode

题目描述

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

  • 如果是有效的 IPv4 地址,返回 "IPv4"
  • 如果是有效的 IPv6 地址,返回 "IPv6"
  • 如果不是上述类型的 IP 地址,返回 "Neither"

IPv4 地址由十进制数和点来表示,每个地址包含 4 个十进制数,其范围为 0 - 255, 用 (“.”) 分割。比如,172.16.254.1

同时,IPv4 地址内的数不会以 0 开头。比如,地址 172.16.254.01 是不合法的。

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

然而,我们不能因为某个组的值为 0,而使用一个空的组,以至于出现 (::) 的情况。 比如, 2001:0db8:85a3::8A2E:0370:7334 是无效的 IPv6 地址。

同时,在 IPv6 地址中,多余的 0 也是不被允许的。比如, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 是无效的。

示例 1:

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

示例 2:

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

示例 3:

输入: IP = “256.256.256.256”
输出: “Neither”
解释: 既不是 IPv4 地址,又不是 IPv6 地址

示例 4:

输入: IP = “2001:0db8:85a3:0:0:8A2E:0370:7334:”
输出: “Neither”

示例 5:

输入: IP = “1e1.4.5.6”
输出: “Neither”

提示:

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

    解题思路

    方法一:遍历整个字符串

  1. class Solution {
  2. public String validIPAddress(String queryIP) {
  3. int len = queryIP.length();
  4. // Neither
  5. if(len < 7 || len > 39){
  6. return "Neither";
  7. }
  8. // if ipv4 7 - 15位
  9. if(len <= 15){
  10. if(checkV4(queryIP, len)){
  11. return "IPv4";
  12. }
  13. }
  14. // 判断 len >= 15
  15. // if ipv6 15 - 39位
  16. if(checkV6(queryIP, len)){
  17. return "IPv6";
  18. }
  19. return "Neither";
  20. }
  21. private boolean checkV4(String queryIP, int len){
  22. int pos = 0;
  23. // 组数
  24. int n = 0;
  25. while(pos < len){
  26. // 判断是否为数字
  27. if(queryIP.charAt(pos) < '0' || queryIP.charAt(pos) > '9'){
  28. return false;
  29. }
  30. // 判断当前组为0时,是否只有0
  31. if(queryIP.charAt(pos) == '0' && queryIP.charAt(pos + 1) != '.'){
  32. return false;
  33. }
  34. // 当前组ip数
  35. int val = 0;
  36. while(pos < len && queryIP.charAt(pos) >='0' && queryIP.charAt(pos) <='9'){
  37. val = val * 10 + queryIP.charAt(pos) - '0';
  38. ++pos;
  39. }
  40. // 如果当前ip数在范围内
  41. if(val >= 0 && val < 256 && n < 4){
  42. ++n;
  43. // 跳过间隔符 如果是最后一组,不用跳过
  44. if(n < 4){
  45. ++pos;
  46. }
  47. }
  48. }
  49. // 返回结果是否为4组Ip
  50. return n == 4;
  51. }
  52. private boolean checkV6(String queryIP, int len){
  53. int pos = 0;
  54. int n = 0;
  55. while(pos < len){
  56. // 判断是否为16进制数
  57. if(!check(queryIP.charAt(pos))){
  58. return false;
  59. }
  60. int val = 0;
  61. // 当前组ip数
  62. while(pos < len && check(queryIP.charAt(pos))){
  63. ++val;
  64. ++pos;
  65. }
  66. // 如果当前ip数在范围内
  67. if(val < 5 && n < 8){
  68. ++n;
  69. // 跳过间隔符 如果是最后一组,不用跳过
  70. if(n < 8){
  71. ++pos;
  72. }
  73. }
  74. }
  75. // 返回结果是否为8组Ip
  76. return n == 8;
  77. }
  78. // 判断是否为16进制数
  79. private boolean check(char c){
  80. return c >= '0' && c <= '9' || c >= 'a' && c <= 'f'|| c >= 'A' && c <= 'F';
  81. }
  82. }
  • 时间复杂度 O(n)
  • 空间复杂度 O(1)