Java&C++题解与拓展——leetcode468.验证IP地址【么的新知识】

每日一题做题记录,参考官方和三叶的题解

题目要求

在这里插入图片描述

思路:双指针

  • 先根据分隔符判断是v4还是v6;
  • 根据不同协议特征分别遍历判断,判断被分隔符分开的每一段是否合法,左指针指段首,右指针向后移动直到遇到分隔符;
  • 最后判断分隔符数量。

Java

class Solution {
    int n;
    public String validIPAddress(String queryIP) {
        n = queryIP.length();
        if(queryIP.indexOf(".") >= 0 && ipv4(queryIP))
            return "IPv4";
        if(queryIP.indexOf(":") >= 0 && ipv6(queryIP))
            return "IPv6";
        return "Neither";
    }

    boolean ipv4(String ip) {
        int splitCnt = 0;
        for(int i = 0; i < n && splitCnt <= 3; ) {
            int j = i, cur = 0; // 被.分隔的段
            // 每一位合法,总数合法
            while(j < n && ip.charAt(j) >= '0' && ip.charAt(j) <= '9' && cur <= 255)
                cur = cur * 10 + (ip.charAt(j++) - '0');
            // ..
            if(i == j)
                return false;
            // 前导0
            if((j - i > 1 && ip.charAt(i) == '0') || (cur > 255))
                return false;
            i = j + 1; // 下一段
            if(j == n)
                continue;
            // 分隔符非法
            if(ip.charAt(j) != '.')
                return false;
            splitCnt++;
        }
        // 分隔符数量和位置都对
        return splitCnt == 3 && ip.charAt(0) != '.' && ip.charAt(n - 1) != '.';
    }
    boolean ipv6(String ip) {
        int splitCnt = 0;
        for(int i = 0; i < n && splitCnt <= 7; ) {
            int j = i;
            // 每一位合法
            while(j < n && ((ip.charAt(j) >= 'a' && ip.charAt(j) <= 'f') || (ip.charAt(j) >= 'A' && ip.charAt(j) <= 'F') || (ip.charAt(j) >= '0' && ip.charAt(j) <= '9')))
                j++;
            // ..或位数超了
            if(i == j || j - i > 4)
                return false;
            i = j + 1;
            if(j == n)
                continue;
            // 分隔符非法
            if(ip.charAt(j) != ':')
                return false;
            splitCnt++;
        }
        // 分隔符数量和位置都对
        return splitCnt == 7 && ip.charAt(0) != ':' && ip.charAt(n - 1) != ':';
    }
}
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

C++

class Solution {
    int n;
public:
    string validIPAddress(string queryIP) {
        n = queryIP.size();
        if(queryIP.find(".") != string::npos && ipv4(queryIP))
            return "IPv4";
        if(queryIP.find(":") != string::npos && ipv6(queryIP))
            return "IPv6";
        return "Neither";
    }
    
    bool ipv4(string ip) {
        int splitCnt = 0;
        for(int i = 0; i < n && splitCnt <= 3; ) {
            int j = i, cur = 0; // 被.分隔的段
            // 每一位合法,总数合法
            while(j < n && ip[j] >= '0' && ip[j] <= '9' && cur <= 255)
                cur = cur * 10 + (ip[j++] - '0');
            // ..
            if(i == j)
                return false;
            // 前导0
            if((j - i > 1 && ip[i] == '0') || (cur > 255))
                return false;
            i = j + 1; // 下一段
            if(j == n)
                continue;
            // 分隔符非法
            if(ip[j] != '.')
                return false;
            splitCnt++;
        }
        // 分隔符数量和位置都对
        return splitCnt == 3 && ip[0] != '.' && ip[n - 1] != '.';
    }
    bool ipv6(string ip) {
        int splitCnt = 0;
        for(int i = 0; i < n && splitCnt <= 7; ) {
            int j = i;
            // 每一位合法
            while(j < n && ((ip[j] >= 'a' && ip[j] <= 'f') || (ip[j] >= 'A' && ip[j] <= 'F') || (ip[j] >= '0' && ip[j] <= '9')))
                j++;
            // ..或位数超了
            if(i == j || j - i > 4)
                return false;
            i = j + 1;
            if(j == n)
                continue;
            // 分隔符非法
            if(ip[j] != ':')
                return false;
            splitCnt++;
        }
        // 分隔符数量和位置都对
        return splitCnt == 7 && ip[0] != ':' && ip[n - 1] != ':';
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

Rust

  • 调用已有的库,然后对定义差异进行一定的修改
impl Solution {
    pub fn valid_ip_address(query_ip: String) -> String {
        use std::net::{Ipv4Addr, Ipv6Addr};
        query_ip
            .parse::<Ipv4Addr>()
            .map(|_| String::from("IPv4"))
            .or(query_ip
                .split(":")
                .map(|x| if x.is_empty() { "g" } else {x}) // 把空字符转为非法字符
                .collect::<Vec<_>>()
                .join(":")
                .parse::<Ipv6Addr>()
                .map(|_| String::from("IPv6")))
            .unwrap_or_else(|_| String::from("Neither"))
    }
}
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

总结

又是快乐的双指针,周末快乐~


欢迎指正与讨论!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值