乐趣区

关于后端:面试高频题难度-15不难但极其常见的双指针模拟

题目形容

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

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

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

无效的 IPv4 地址 是 “x1.x2.x3.x4” 模式的 IP 地址。其中 $ 0 <= x_i <= 255$ 且 $x_i$ 不能蕴含 前导零。

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

  • $1 <= x_i.length <= 4$
  • $x_i$ 是一个 十六进制字符串,能够蕴含数字、小写英文字母 ('a''f' ) 和大写英文字母('A''F' )。
  • 在 $x_i$ 中容许前导零。

例如 "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] != ':';
    }
}
  • 工夫复杂度:$O(n)$
  • 空间复杂度:应用 toCharArray 操作会产生新数组,复杂度为 $O(n)$,应用 charAt 操作代替复杂度为 $O(1)$

最初

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

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

为了不便各位同学可能电脑上进行调试和提交代码,我建设了相干的仓库:https://github.com/SharingSource/LogicStack-LeetCode。

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

更多更全更热门的「口试 / 面试」相干材料可拜访排版精美的 合集新基地 🎉🎉

本文由 mdnice 多平台公布

退出移动版