DSA patterns

Validate IP Address

mediumStrings Must-do

Problem statement

Given a string queryIP, return "IPv4" if it is a valid IPv4 address, "IPv6" if it is a valid IPv6 address, and "Neither" otherwise. Use these rules:

  • IPv4: exactly four parts separated by .. Each part is 1 to 3 decimal digits with a value from 0 to 255, and has no leading zero unless the part is exactly 0. So 10.0.1.15 is valid, while 10.0.01.15 and 10.0.1.256 are not.
  • IPv6: exactly eight groups separated by :. Each group is 1 to 4 hexadecimal digits (0-9, a-f, A-F). Leading zeros are allowed. The shortened :: form is not accepted here.

Nothing else may appear in the string: no spaces, no signs, no empty parts.

Examples

Example 1

Input: queryIP = "10.0.1.15"

Output: "IPv4"

Example 2

Input: queryIP = "fd00:1a2b:0:0:0:0:ff:9"

Output: "IPv6"

Explanation: Eight groups, each 1 to 4 hex digits. Case and leading zeros don't matter for IPv6.

Hints

Approach

Split and check each part by hand.

  1. If the string contains a ., split on . and require exactly 4 parts. Each part must be 1 to 3 characters, all in 0-9, must not start with 0 unless it is exactly "0", and must be at most 255.
  2. Otherwise, if it contains a :, split on : and require exactly 8 parts. Each must be 1 to 4 characters, all hexadecimal digits.
  3. Anything else is "Neither".

In Java, call split(regex, -1). Without the -1, Java silently drops trailing empty strings, so "1.2.3.4." would split into four parts and wrongly pass.

ComplexityTime O(n)Space O(n)
Python
class Solution:
def validIPAddress(self, queryIP: str) -> str:
if "." in queryIP and self._is_v4(queryIP):
return "IPv4"
if ":" in queryIP and self._is_v6(queryIP):
return "IPv6"
return "Neither"
def _is_v4(self, ip: str) -> bool:
parts = ip.split(".")
if len(parts) != 4:
return False
for p in parts:
if not 1 <= len(p) <= 3 or any(c not in "0123456789" for c in p):
return False
if len(p) > 1 and p[0] == "0": # no leading zeros
return False
if int(p) > 255:
return False
return True
def _is_v6(self, ip: str) -> bool:
hexdigits = set("0123456789abcdefABCDEF")
parts = ip.split(":")
if len(parts) != 8:
return False
return all(1 <= len(p) <= 4 and all(c in hexdigits for c in p) for p in parts)

Follow-up questions

  • Accept the compressed IPv6 form with :: and expand it to eight groups.
  • Validate CIDR notation such as 10.0.0.0/16, and check whether an address falls inside it.

Frequently asked questions

They follow the real standards, which differ from this problem's rules: real IPv6 allows the :: shorthand, and InetAddress.getByName may try a DNS lookup for anything that isn't a literal. In production code, prefer the library; in the interview, the point is writing the validation yourself.

Some parsers read a part like 010 as octal (8), so 10.0.010.1 can mean different addresses to different tools. Rejecting leading zeros removes that ambiguity.

Validating addresses from config files, API input or firewall rules is routine for network, SRE and platform engineers. The question checks careful parsing: exact part counts, empty parts, ranges and character sets.