diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 79985347..d0c11c0f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -300,6 +300,7 @@ - [0374. 猜数字大小 Guess Number Higher or Lower](leetcode/0374.guess-number-higher-or-lower/index.md) - [0394. 字符串解码 Decode String](leetcode/0394.decode-string/index.md) - [0401-0500](leetcode/by-id/0401-0500.md) + - [0468. 验证IP地址 Validate IP Address](leetcode/0468.validate-ip-address/index.md) - [0485. 最大连续1的个数 Max Consecutive Ones](leetcode/0485.max-consecutive-ones/index.md) - [0496. 下一个更大元素 I Next Greater Element I](leetcode/0496.next-greater-element-i/index.md) - [0501-0600](leetcode/by-id/0501-0600.md) diff --git a/src/leetcode/0468.validate-ip-address/.gitignore b/src/leetcode/0468.validate-ip-address/.gitignore new file mode 100644 index 00000000..95811e00 --- /dev/null +++ b/src/leetcode/0468.validate-ip-address/.gitignore @@ -0,0 +1 @@ +/main diff --git a/src/leetcode/0468.validate-ip-address/Cargo.toml b/src/leetcode/0468.validate-ip-address/Cargo.toml new file mode 100644 index 00000000..efdb4fd5 --- /dev/null +++ b/src/leetcode/0468.validate-ip-address/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "lc-0468-validate-ip-address" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] diff --git a/src/leetcode/0468.validate-ip-address/Makefile b/src/leetcode/0468.validate-ip-address/Makefile new file mode 100644 index 00000000..b686101f --- /dev/null +++ b/src/leetcode/0468.validate-ip-address/Makefile @@ -0,0 +1,3 @@ + +build: main.cpp + g++ -g main.cpp -o main diff --git a/src/leetcode/0468.validate-ip-address/index.md b/src/leetcode/0468.validate-ip-address/index.md new file mode 100644 index 00000000..13f2e96d --- /dev/null +++ b/src/leetcode/0468.validate-ip-address/index.md @@ -0,0 +1,31 @@ +# 0468. 验证IP地址 Validate IP Address + +[问题描述](https://leetcode.com/problems/validate-ip-address) + +这个是处理字符串的问题. + +步骤大致如下: +- 先检查是不是 ipv4, 如果是, 直接返回 + - 先以 `.` 将字符串分隔成多个部分, parts + - parts 数组的长度应该是 4 + - 检查每一部分字符串 + - 长度在 [1..3] 之间 + - 如果以 `0` 为前缀的话, 只能包含 `0` + - 检查里面的字符, 只能包含 `0-9` 这10 个字符, 可以用 `std::isdigit(c)` + - 将它转换成整数, 数值范围是 [0..255] +- 再检查是不是 ipv6, 如果是, 就返回 + - 以 `:` 将字符串分隔成多个部分, parts + - parts 数组的长度是 8 + - 检查每一部分字符串 + - 字符串长度是 [1..4] 之间 + - 检查里面的字符, 只能包含 0-9, a-f, A-F这些字符, 可以用 `std::is_xdigit(c)` + - 不需要把它再转换成整数 +- 返回 `Neither` + +以下是代码实现: + +## Rust + +```rust +{{#include src/main.rs:5:82}} +``` diff --git a/src/leetcode/0468.validate-ip-address/main.cpp b/src/leetcode/0468.validate-ip-address/main.cpp new file mode 100644 index 00000000..171c0a4a --- /dev/null +++ b/src/leetcode/0468.validate-ip-address/main.cpp @@ -0,0 +1,116 @@ +// Copyright (c) 2024 Xu Shaohua . All rights reserved. +// Use of this source is governed by General Public License that can be found +// in the LICENSE file. + +#include + +#include +#include +#include + +class Solution { + public: + static bool isIPv4(const std::string& query) { + // 用 `.` 来分隔各部分 + // 并判断每个部分是有效的数值 + // 数值不带有前缀0 + + if (query[0] == '.' || query[query.size() - 1] == '.') { + return false; + } + std::stringstream ss(query); + std::string part; + int part_count = 0; + while (std::getline(ss, part, '.')) { + part_count += 1; + // 数值不带有前缀0 + if (part[0] == '0' && part.size() > 1) { + return false; + } + if (part.size() < 1 || part.size() > 3) { + return false; + } + // 判断字符的范围, 0-9 + for (char c : part) { + if (!std::isdigit(c)) { + return false; + } + } + + const int val = std::stoi(part); + // 不是有效的整数 + if (val == 0 && part != "0") { + return false; + } + // 数值范围是 0..255 + if (val < 0 || val > 255) { + return false; + } + } + + // 要有4个部分 + return part_count == 4; + } + + static bool isIPv6(const std::string& query) { + // 使用 `:` 作为分隔符 + // 每个部分是16进制的整数, 16进制支持大小写, 最多包含4个字符 + // 可以有0作为前缀 + // 不需要考虑缩写 + + if (query[0] == ':' || query[query.size() - 1] == ':') { + return false; + } + + std::stringstream ss(query); + std::string part; + int part_count = 0; + while (std::getline(ss, part, ':')) { + // 1-4个字符 + if (part.size() < 1 || part.size() > 4) { + return false; + } + + for (char c : part) { + // 判断字符的范围, 0-9, a-f, A-F + if (!std::isxdigit(c)) { + return false; + } + } + part_count += 1; + } + + return part_count == 8; + } + + static std::string validIPAddress(std::string queryIP) { + if (isIPv4(queryIP)) { + return "IPv4"; + } + if (isIPv6(queryIP)) { + return "IPv6"; + } + return "Neither"; + } +}; + +void checkSolution() { + { + const std::string s1 = "2001:0db8:85a3:0:0:8A2E:0370:7334:"; + const std::string expected = "Neither"; + const std::string out = Solution::validIPAddress(s1); + assert(out == expected); + } + + { + const std::string s1 = "1e1.4.5.6"; + const std::string expected = "Neither"; + const std::string out = Solution::validIPAddress(s1); + assert(out == expected); + } +} + +int main() { + checkSolution(); + return 0; +} diff --git a/src/leetcode/0468.validate-ip-address/src/main.rs b/src/leetcode/0468.validate-ip-address/src/main.rs new file mode 100644 index 00000000..a362673f --- /dev/null +++ b/src/leetcode/0468.validate-ip-address/src/main.rs @@ -0,0 +1,114 @@ +// Copyright (c) 2024 Xu Shaohua . All rights reserved. +// Use of this source is governed by General Public License that can be found +// in the LICENSE file. + +fn is_ipv4(query: &str) -> bool { + // 用 `.` 来分隔各部分 + // 并判断每个部分是有效的数值 + // 数值不带有前缀0 + + let parts: Vec<&str> = query.split('.').collect(); + if parts.len() != 4 { + return false; + } + + for part in parts { + if part.len() < 1 || part.len() > 3 { + return false; + } + + // 数值不带有前缀0 + if part.len() > 1 && part.starts_with("0") { + return false; + } + + // 判断字符的范围, 0-9 + for c in part.chars() { + if !c.is_ascii_digit() { + return false; + } + } + + if let Ok(val) = part.parse::() { + // 数值范围是 0..255 + if val < 0 || val > 255 { + return false; + } + } else { + // 不是有效的整数 + return false; + } + } + + true +} + +fn is_ipv6(query: &str) -> bool { + // 使用 `:` 作为分隔符 + // 每个部分是16进制的整数, 16进制支持大小写, 最多包含4个字符 + // 可以有0作为前缀 + // 不需要考虑缩写 + + let parts: Vec<&str> = query.split(':').collect(); + if parts.len() != 8 { + return false; + } + + for part in parts { + // 1-4个字符 + if part.len() < 1 || part.len() > 4 { + return false; + } + + for c in part.chars() { + // 判断字符的范围, 0-9, a-f, A-F + if !c.is_ascii_hexdigit() { + return false; + } + } + } + + true +} + +pub fn valid_ip_address1(query_ip: String) -> String { + if is_ipv4(&query_ip) { + "IPv4".to_owned() + } else if is_ipv6(&query_ip) { + "IPv6".to_owned() + } else { + "Neither".to_owned() + } +} + +pub type SolutionFn = fn(String) -> String; + +fn check_solution(func: SolutionFn) { + { + let s1 = "2001:0db8:85a3:0:0:8A2E:0370:7334:".to_owned(); + let expected = "Neither"; + let out = func(s1); + assert_eq!(out, expected); + } + + { + let s1 = "1e1.4.5.6".to_owned(); + let expected = "Neither"; + let out = func(s1); + assert_eq!(out, expected); + } +} + +fn main() { + check_solution(valid_ip_address1); +} + +#[cfg(test)] +mod tests { + use super::{check_solution, valid_ip_address1}; + + #[test] + fn test_valid_ip_address1() { + check_solution(valid_ip_address1); + } +} diff --git a/src/leetcode/tags/string/index.md b/src/leetcode/tags/string/index.md index 2f6b78f9..9f507d8d 100644 --- a/src/leetcode/tags/string/index.md +++ b/src/leetcode/tags/string/index.md @@ -15,8 +15,12 @@ ## 中级 -- [6. Z 字形变换](https://leetcode.com/problems/zigzag-conversion) -- [8. 字符串转换整数(atoi)](https://leetcode.com/problems/string-to-integer-atoi) -- [17.电话号码的字母组合](https://leetcode.com/problems/letter-combinations-of-a-phone-number) -- [165.比较版本号](https://leetcode.com/problems/compare-version-numbers) -- [2414. Length of the Longest Alphabetical Continuous Substring](https://leetcode.com/problems/length-of-the-longest-alphabetical-continuous-substring/description/) \ No newline at end of file +1. [0468. 验证IP地址 Validate IP Address](../../0468.validate-ip-address/index.md) + +TODO: + +- [0006. Z 字形变换](https://leetcode.com/problems/zigzag-conversion) +- [0008. 字符串转换整数(atoi)](https://leetcode.com/problems/string-to-integer-atoi) +- [0017.电话号码的字母组合](https://leetcode.com/problems/letter-combinations-of-a-phone-number) +- [0165.比较版本号](https://leetcode.com/problems/compare-version-numbers) +- [2414. Length of the Longest Alphabetical Continuous Substring](https://leetcode.com/problems/length-of-the-longest-alphabetical-continuous-substring/description/)