LeetCode 468. 驗證IP地址 - 詳細解析

文章目錄

  • LeetCode 468. 驗證IP地址 - 詳細解析
    • 題目描述
      • IPv4驗證規則:
      • IPv6驗證規則:
    • 最優Java解決方案(注釋完整版)
    • 關鍵變量含義及代碼技巧
      • 代碼技巧詳解
        • 1. 前導零檢查的最佳實踐
        • 2. IPv6為什么不能用Character.isDigit()
        • 3. 針對性注釋設計
    • 算法核心思路
    • 可視化演示過程
      • 測試用例1:有效IPv4 - "172.16.254.1"(優化版演示)
      • 測試用例2:有效IPv6 - "2001:0db8:85a3:0:0:8A2E:0370:7334"(優化版演示)
      • 測試用例3:無效IPv4(前導零)- "192.168.01.1"(優化版演示)
      • 測試用例4:無效IPv4(超出范圍)- "256.256.256.256"(優化版演示)
      • 測試用例5:無效IPv6(段過長)- "02001:0db8:85a3:0000:0000:8a2e:0370:7334"
      • 測試用例6:無效格式(非法字符)- "192.168@1.1"
    • 算法復雜度分析
    • 關鍵技術點詳解
      • String的isEmpty() vs isBlank()方法對比
        • 詳細對比示例:
        • 在IP驗證中的應用:
        • 安全的null檢查:
      • split() 方法的 limit 參數
    • 代碼優化技巧總結
    • 代碼優勢對比
    • 常見陷阱

LeetCode 468. 驗證IP地址 - 詳細解析

題目描述

給定一個字符串 queryIP。如果是有效的 IPv4 地址,返回 “IPv4” ;如果是有效的 IPv6 地址,返回 “IPv6” ;如果不是上述類型的 IP 地址,返回 “Neither” 。

IPv4驗證規則:

  • 格式:“x1.x2.x3.x4”
  • 0 <= xi <= 255
  • xi 不能包含前導零(除了"0"本身)

IPv6驗證規則:

  • 格式:“x1:x2:x3:x4:x5:x6:x7:x8”
  • 1 <= xi.length <= 4
  • xi 是十六進制字符串(0-9, a-f, A-F)
  • 允許前導零

最優Java解決方案(注釋完整版)

class Solution {public String validIPAddress(String queryIP) {if (queryIP.contains(".")) {return isValidIPV4(queryIP) ? "IPv4" : "Neither";} else if (queryIP.contains(":")) {return isValidIPV6(queryIP) ? "IPv6" : "Neither";} else return "Neither";}boolean isValidIPV4(String ip) {String[] parts = ip.split("\\.", -1);if (parts.length != 4) {return false;}for (String part : parts) {int n = part.length();if (n == 0 || n > 3) { // 針對""和2555的輸入return false;}if (n > 1 && part.startsWith("0")) { // 針對10.01.1.1輸入,前導零return false;}for (char c : part.toCharArray()) { // 針對非數字輸入if (!Character.isDigit(c)) {return false;}}int num = Integer.parseInt(part); // 針對256.0.0.1輸入if (!(num >= 0 && num <= 255)) {return false;}}return true;}boolean isValidIPV6(String ip) {String[] parts = ip.split(":", -1);if (parts.length != 8) {return false;}for (String part : parts) {int n = part.length();if (n == 0 || n > 4) { // 針對空串和11111輸入return false;}for (char c : part.toCharArray()) {// 這里不能替換為Character.isDigit(c)if (!((c >= '0' && c <= '9') ||(c >= 'a' && c <= 'f') ||(c >= 'A' && c <= 'F'))) {return false;}}}return true;}
}

關鍵變量含義及代碼技巧

變量名含義作用
queryIP輸入的待驗證IP字符串算法的輸入參數
parts分割后的IP段數組存儲按".“或”:"分割的各個部分
part單個IP段字符串用于驗證每個獨立的IP段
nIP段的長度int n = part.length() 提高代碼可讀性
numIPv4段的整數值用于檢查IPv4段是否在0-255范圍內
c字符變量用于逐字符檢查是否符合格式要求

代碼技巧詳解

1. 前導零檢查的最佳實踐
if (n > 1 && part.startsWith("0")) { // 針對10.01.1.1輸入,前導零return false;
}

為什么用 startsWith("0") 而不是 charAt(0) == '0'

  • 更語義化,表達"以0開頭"的意圖更清晰
  • startsWith() 內部已經做了邊界檢查,更安全
2. IPv6為什么不能用Character.isDigit()
// 這里不能替換為Character.isDigit(c)
if (!((c >= '0' && c <= '9') ||(c >= 'a' && c <= 'f') ||(c >= 'A' && c <= 'F'))) {return false;
}

原因分析:

  • Character.isDigit(c) 只檢查數字字符(0-9)
  • IPv6需要十六進制字符:數字(0-9) + 字母(a-f, A-F)
  • 必須手動檢查三個范圍:數字、小寫字母、大寫字母
3. 針對性注釋設計

代碼中的注釋都標明了具體要處理的邊界情況:

  • // 針對""和2555的輸入 → 長度檢查
  • // 針對10.01.1.1輸入,前導零 → 前導零檢查
  • // 針對非數字輸入 → 字符合法性檢查
  • // 針對256.0.0.1輸入 → 數值范圍檢查
  • // 針對空串和11111輸入 → IPv6長度檢查

算法核心思路

  1. 預判斷:通過檢查是否包含".“或”:"來初步判斷IP類型
  2. 分割驗證:將IP按分隔符分割成段,驗證段數是否正確
  3. 逐段檢查:對每個段進行格式和數值范圍驗證
  4. 字符級驗證:確保每個字符都符合對應IP類型的要求

可視化演示過程

測試用例1:有效IPv4 - “172.16.254.1”(優化版演示)

步驟1:初步判斷
queryIP = "172.16.254.1"
包含"." ? → 進入IPv4驗證步驟2:分割并長度檢查
parts = ["172", "16", "254", "1"]
parts.length = 4 ? → 段數正確,繼續驗證步驟3:逐段內聯驗證
part[0] = "172"
├── 長度檢查: 3 ≤ 3 ?
├── 前導零檢查: 首字符'1' ≠ '0' ?
├── 字符檢查: '1','7','2' 全為數字 ?
└── 數值檢查: Integer.parseInt("172") = 172 ≤ 255 ?part[1] = "16"
├── 長度檢查: 2 ≤ 3 ?
├── 前導零檢查: 首字符'1' ≠ '0' ?
├── 字符檢查: '1','6' 全為數字 ?
└── 數值檢查: Integer.parseInt("16") = 16 ≤ 255 ?part[2] = "254"
├── 長度檢查: 3 ≤ 3 ?
├── 前導零檢查: 首字符'2' ≠ '0' ?
├── 字符檢查: '2','5','4' 全為數字 ?
└── 數值檢查: Integer.parseInt("254") = 254 ≤ 255 ?part[3] = "1"
├── 長度檢查: 1 ≤ 3 ?
├── 前導零檢查: 長度=1,無需檢查 ?
├── 字符檢查: '1' 為數字 ?
└── 數值檢查: Integer.parseInt("1") = 1 ≤ 255 ?結果:返回 "IPv4"

測試用例2:有效IPv6 - “2001:0db8:85a3:0:0:8A2E:0370:7334”(優化版演示)

步驟1:初步判斷
queryIP = "2001:0db8:85a3:0:0:8A2E:0370:7334"
不包含"." 但包含":" ? → 進入IPv6驗證步驟2:分割并長度檢查
parts = ["2001", "0db8", "85a3", "0", "0", "8A2E", "0370", "7334"]
parts.length = 8 ? → 段數正確,繼續驗證步驟3:逐段內聯驗證
part[0] = "2001"
├── 長度檢查: 4 ≤ 4 ?
└── 內聯十六進制檢查:│ '2': '0'≤'2'≤'9' ?│ '0': '0'≤'0'≤'9' ?│ '0': '0'≤'0'≤'9' ?│ '1': '0'≤'1'≤'9' ?part[1] = "0db8"
├── 長度檢查: 4 ≤ 4 ?
└── 內聯十六進制檢查:│ '0': '0'≤'0'≤'9' ?│ 'd': 'a'≤'d'≤'f' ?│ 'b': 'a'≤'b'≤'f' ?│ '8': '0'≤'8'≤'9' ?part[5] = "8A2E"
├── 長度檢查: 4 ≤ 4 ?
└── 內聯十六進制檢查:│ '8': '0'≤'8'≤'9' ?│ 'A': 'A'≤'A'≤'F' ?│ '2': '0'≤'2'≤'9' ?│ 'E': 'A'≤'E'≤'F' ?... (其他段類似驗證) ...結果:返回 "IPv6"

測試用例3:無效IPv4(前導零)- “192.168.01.1”(優化版演示)

步驟1:初步判斷
queryIP = "192.168.01.1"
包含"." ? → 進入IPv4驗證步驟2:分割并長度檢查
parts = ["192", "168", "01", "1"]
parts.length = 4 ? → 段數正確,繼續驗證步驟3:逐段內聯驗證
part[0] = "192" ? (驗證通過)
part[1] = "168" ? (驗證通過)
part[2] = "01"
├── 長度檢查: 2 ≤ 3 ?
├── 前導零檢查: 長度>1 且 首字符='0' ?
└── 立即返回false,無需進行后續計算結果:返回 "Neither"

測試用例4:無效IPv4(超出范圍)- “256.256.256.256”(優化版演示)

步驟1:初步判斷
queryIP = "256.256.256.256"
包含"." ? → 進入IPv4驗證步驟2:分割并長度檢查
parts = ["256", "256", "256", "256"]
parts.length = 4 ? → 段數正確,繼續驗證步驟3:逐段內聯驗證
part[0] = "256"
├── 長度檢查: 3 ≤ 3 ?
├── 前導零檢查: 首字符'2' ≠ '0' ?
├── 字符檢查: '2','5','6' 全為數字 ?
└── 數值檢查: Integer.parseInt("256") = 256 > 255 ?結果:返回 "Neither"

測試用例5:無效IPv6(段過長)- “02001:0db8:85a3:0000:0000:8a2e:0370:7334”

步驟1:初步判斷
queryIP = "02001:0db8:85a3:0000:0000:8a2e:0370:7334"
不包含"." 但包含":" ? → 可能是IPv6步驟2:分割IP
parts = ["02001", "0db8", "85a3", "0000", "0000", "8a2e", "0370", "7334"]
parts.length = 8 ? → 段數正確步驟3:逐段驗證
part[0] = "02001"
├── 長度檢查: 5 > 4 ?
└── 驗證失敗!結果:返回 "Neither"

測試用例6:無效格式(非法字符)- “192.168@1.1”

步驟1:初步判斷
queryIP = "192.168@1.1"
包含"." ? → 可能是IPv4步驟2:分割IP
parts = ["192", "168@1", "1"]
parts.length = 3 ≠ 4 ?結果:返回 "Neither"

算法復雜度分析

  • 時間復雜度:O(n),其中n是字符串長度。需要遍歷整個字符串進行分割和驗證
  • 空間復雜度:O(1),除了存儲分割后的段數組,不需要額外空間

關鍵技術點詳解

String的isEmpty() vs isBlank()方法對比

在IP驗證中,我們經常需要檢查字符串是否為空,了解這兩個方法的區別很重要:

方法作用Java版本檢查內容
isEmpty()檢查長度是否為0Java 6+只檢查 length() == 0
isBlank()檢查是否為空或只有空白字符Java 11+檢查 isEmpty() || 全為空白字符
詳細對比示例:
String str1 = "";           // 空字符串
String str2 = " ";          // 一個空格
String str3 = "  \t\n ";    // 多個空白字符(空格、制表符、換行符)
String str4 = " a ";        // 包含非空白字符
String str5 = null;         // null值// isEmpty() 結果:
str1.isEmpty()true   ? (長度為0)
str2.isEmpty()false  ? (長度為1)
str3.isEmpty()false  ? (長度為4)
str4.isEmpty()false  ? (長度為3)
// str5.isEmpty() → NullPointerException!// isBlank() 結果 (Java 11+):
str1.isBlank()true   ? (長度為0)
str2.isBlank()true   ? (只有空白字符)
str3.isBlank()true   ? (只有空白字符)
str4.isBlank()false  ? (包含非空白字符)
// str5.isBlank() → NullPointerException!
在IP驗證中的應用:
// 檢查IP段是否為空的不同方式
private boolean isValidIPv4Part(String part) {// 方式1:直接檢查長度(推薦)if (part.length() == 0) return false;// 方式2:使用isEmpty()(等效)if (part.isEmpty()) return false;// 方式3:使用isBlank()(Java 11+,更嚴格)if (part.isBlank()) return false; // 會拒絕 " " 這樣的空格段// ... 其他驗證邏輯
}
安全的null檢查:
// 推薦的安全檢查方式
public static boolean isNullOrEmpty(String str) {return str == null || str.isEmpty();
}public static boolean isNullOrBlank(String str) {return str == null || str.isBlank(); // Java 11+
}

split() 方法的 limit 參數

String[] parts = ip.split("\\.", -1);

split(regex, limit) 中的 limit 參數控制分割行為:

limit值行為示例
limit > 0最多分割成limit個部分"a.b.c".split("\\.", 2)["a", "b.c"]
limit = 0默認行為,移除尾部空字符串"a.b.".split("\\.")["a", "b"]
limit < 0保留所有空字符串(包括尾部)"a.b.".split("\\.", -1)["a", "b", ""]

為什么IP驗證必須用 -1

// 測試案例對比
String ip1 = "192.168.1.";     // 末尾多點號
String ip2 = "192..168.1";     // 連續點號// 不使用-1 (默認行為)
ip1.split("\\.")["192", "168", "1"]     // 長度=3,錯誤!應該是4段
ip2.split("\\.")["192", "", "168", "1"] // 長度=4,但漏掉了空段檢測// 使用-1 (正確行為)  
ip1.split("\\.", -1)["192", "168", "1", ""] // 長度=4,能檢測到末尾空段
ip2.split("\\.", -1)["192", "", "168", "1"] // 長度=4,能檢測到中間空段

代碼優化技巧總結

  1. 關鍵的 split(-1):確保捕獲所有邊界情況,包括末尾和中間的空段
  2. 長度預判斷:直接檢查分割后數組長度,不符合直接返回false
  3. 語義化變量命名:使用 int n = part.length() 提高代碼可讀性
  4. 語義化方法調用:使用 part.startsWith("0") 替代 part.charAt(0) == '0'
  5. 詳細的針對性注釋:每個檢查都注明具體處理的邊界情況
  6. 精確的字符范圍檢查:IPv6手動檢查三個字符范圍,不使用Character.isDigit()
  7. 清晰的條件表達式:使用 !(num >= 0 && num <= 255) 明確表達范圍檢查

代碼優勢對比

優化項傳統寫法當前實現優勢說明
變量命名part.length() 重復調用int n = part.length()提高可讀性,減少重復計算
前導零檢查part.charAt(0) == '0'part.startsWith("0")語義更清晰,表達意圖更直接
注釋設計簡單功能注釋針對性邊界情況注釋明確每個檢查要處理的具體問題
字符范圍檢查使用庫函數或正則手動三范圍檢查IPv6需求下更精確,避免誤判
條件表達式num < 0 || num > 255!(num >= 0 && num <= 255)邏輯更直觀,表達"不在范圍內"
長度預檢查在循環中檢查預先檢查數組長度提早退出,避免無效處理

常見陷阱

  1. 忘記檢查前導零(IPv4)
  2. 未正確處理空段(如連續分隔符)
  3. 字符范圍檢查不全面(IPv6的大小寫字母)
  4. 數值范圍檢查遺漏邊界值

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/921496.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/921496.shtml
英文地址,請注明出處:http://en.pswp.cn/news/921496.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

新能源研發,用新型實驗記錄本:ELN

新能源&#xff08;材料&#xff09;研發如火如荼&#xff0c;競爭激烈。以電池為例&#xff0c;新能源汽車的崛起、儲能技術的突破&#xff0c;讓電池成為了能源領域的“新寵”。電池研發已經成為熱門賽場&#xff0c;各研發團隊都在與時間賽跑&#xff0c;試圖維持優勢或彎道…

大語言模型領域最新進展

CSDN大禮包《人工智能大模型課程》 CSDN大禮包《人工智能平臺設計開發課程課程》

【網安干貨】--計算機網絡知識梳理總結(二)

這是計算機網絡知識梳理的第二篇&#xff0c;真正去梳理才發現內容好多好多好多好多好多啊…怕是預計要寫四篇 注意&#xff1a;如果看不清可以右鍵復制圖片鏈接到瀏覽器訪問或另存為照片并放大查看 計算機網絡2 計算機網絡協議2.1 網絡協議的定義與核心要素2.1.1 協議的定義2.…

百度前端社招面經二

社招 百度 前端開發 二面 base 北京 react 17 和 18 的差異react的響應式原理&#xff0c;js是如何驅動模塊的webpacke 4 和 5 差異webpacke 熱更新原理。Tree Shaking 是干嘛的import 和 require 區別&#xff0c;都會被Tree Shaking嗎隱藏元素的幾種方式三欄布局&#xff0c;…

結合prompt分析NodeRAG的build過程

之前介紹了NodeRAG的節點類型和安裝過程。 linux環境conda安裝NodeRAG示例-CSDN博客 這里嘗試從prompt代碼角度分析NodeRAG如何將文檔轉化為節點、關系。 1 整體處理流程 NodeRAG定義了如下所示狀態及處理流程。 # define the state to pipeline mapping self.state_pipelin…

我改寫的二分法XML轉CSV文件程序速度追上了張澤鵬先生的

以下是美團龍貓初稿&#xff0c;我改正&#xff0c;DeepSeek重新格式化的代碼。 重要改正點&#xff1a; 1.二分查找用goto控制迭代&#xff0c;返回<row的正確位置 2.在緩沖區頭填上父標簽使expat能連續解析不報錯 #include <stdio.h> #include <stdlib.h> #in…

使用Docker安裝Stirling-PDF(PDF工具)

1、官方Web端 詳見&#xff1a;https://stirlingpdf.io/?langzh_CN 2、安裝Docker 合集&#xff1a;Docker安裝與使用 3、安裝Stirling-PDF 詳見&#xff1a; https://docs.stirlingpdf.com/Installation/Docker%20Install https://hub.docker.com/r/stirlingtools/stirli…

【開題答辯全過程】以 基于微信小程序的“XIN”學生組織管理系統為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

Iwip驅動8211FS項目——MPSOC實戰1

硬件設計采用RTL8211FS芯片&#xff0c;vitis默認的IWIP庫不支持此芯片。 網口相關知識可以翻看前期文章 以太網PHY_MDIO通信&#xff08;基于RTL8211&#xff09;--FPGA學習筆記22-CSDN博客 以太網ARP協議——FPGA學習筆記23_fpga以太網學習-CSDN博客 以太網ICMP協議(ping…

《Science》神經炎癥綜述思路套用:從機制到跨領域研究范式

2025 年 6 月首都醫科大學團隊在《Science》發表的綜述《Immunological dimensions of neurological disease: from mechanisms to therapeutics》(神經疾病的免疫維度:從機制到療法),系統性解析了神經炎癥的動態演變規律與雙面性,提出階段化、精準化治療新范式。本文基于…

嵌入式學習筆記--Linux系統編程階段--DAY07進程間通信--存儲映射和共享內存

1.存儲映射存儲映射 I/O (Memory-mapped I/O) 使一個磁盤文件與存儲空間中的一個緩沖區相映射。于是當從緩沖區中取數據&#xff0c;就相當于讀文件中的相應字節。于此類似&#xff0c;將數據存入緩沖區&#xff0c;則相應的字節就自動寫入文件。這樣&#xff0c;就可在不適用 …

.Net程序員就業現狀以及學習路線圖(四)

一、.Net程序員就業現狀分析 1. 市場需求與崗位分布 2025年數據顯示&#xff0c;.Net開發崗位在全國IT崗位中占比約0.009%&#xff0c;主要集中在一線城市如深圳、上海等地 2 4。行業分布呈現以下特點&#xff1a;?軟件行業?&#xff1a;占比43.3% ?研發領域?&#xff1a;占…

Monorepo 是什么?如何使用并寫自己的第三方庫

1. 什么是 Monorepo&#xff1f; Monorepo&#xff08;單倉庫&#xff09;指的是把多個項目/包放在一個代碼倉庫里統一管理。常見結構&#xff1a; /repo-root/packages/ui-lib/utils/apps/web-apppackage.jsonpnpm-workspace.yaml好處&#xff1a; 內部庫能直接共享&#xff0…

使用CI/CD部署后端項目(gin)

寫在前面&#xff1a;使用CI/CD部署gin項目到服務器中 前端可以參考&#xff1a;使用CI/CD部署nextjs項目 使用 GitHub Actions 配置后端 CI/CD&#xff08;含部署到服務器&#xff09; 本文檔介紹如何在 GitHub 倉庫中配置 CI/CD&#xff0c;將 PROJECT_NAME 項目自動構建并…

Coze添加知識庫解析的Embedding和PaddleOCR模型配置

1. Embedding模型配置 使用ollama模型&#xff0c;導入qwen3的embedding-8B模型&#xff0c;導入流程參考&#xff1a; Ollama離線部署模型 qwen3-Embedding模型文件可從魔塔社區下載&#xff1a; Qwen3-Embedding-8B 1.2 Coze配置 在coze_studio/docker目錄下輸入: vim .en…

02-Media-6-rtsp_server.py 使用RTSP服務器流式傳輸H264和H265編碼視頻和音頻的示例程序

rtsp_server.py 是使用k230的板載攝像頭和WIFI聯網功能,使用RTSP服務器流式傳輸視頻和音頻的程序示例。程序核心是創建了一個RtspServer類,該類用于初始化、啟動、停止RTSP服務器,并進行視頻和音頻的流傳輸。 一、首先,程序導入必要的模塊,包括視頻編碼、傳感器、媒體處理…

13-Java-面向對象-封裝和this關鍵字

文章目錄封裝this關鍵字封裝 告訴我們&#xff0c;如何正確設計對象的屬性和方法。原則&#xff1a;對象代表什么&#xff0c;就得封裝對應的數據&#xff0c;并提供數據對應的行為 package common;/*** Author: 大海* Date: 2025-09-06*/public class GirlFriend {/*private…

三高項目-緩存設計

三高項目-緩存設計 分流、并發 導流&#xff1a;將原本復雜操作的請求&#xff0c;引導到簡單的操作上。以后再來查&#xff0c;不需要經過復雜的計算。 成本&#xff1a;空間&#xff0c;收益&#xff1a;節省了時間。 不要以為僅僅是 redis&#xff0c;map等。 對應。kv…

happen-before原則

什么是 happen-before 原則&#xff1f; happen-before 是一個邏輯關系&#xff0c;用于描述兩個操作之間的 “先后順序”—— 如果操作 A happen-before 操作 B&#xff0c;那么 A 的執行結果必須對 B 可見&#xff0c;且 A 的執行順序在邏輯上先于 B。也就是保證指令有序性和…

4.1 機器學習 - 評估指標

模型評估是判斷 “模型是否有效” 的核心環節&#xff0c;需結合任務類型&#xff08;分類 / 回歸&#xff09;、數據分布&#xff08;如類別不平衡&#xff09;和商業目標選擇指標。本節聚焦分類任務的核心評估指標&#xff0c;從定義、計算邏輯到適用場景逐一拆解&#xff0c…