Validate an IP Address is a classic string-parsing interview problem. There is no clever data structure here — the whole challenge is reading the spec carefully and turning each rule into one small, exact check. Miss a rule and a sneaky input slips through.
Problem. Given a string s, return True if it is a valid IPv4 address. A valid IPv4 address is
four numbers joined by dots, where each number is between 0 and 255 and has no leading zeros
(except the number 0 itself, written as a single 0).
Example: s = "192.168.0.1" → True. But "192.168.01.1" → False (leading zero) and
"256.1.1.1" → False (256 is out of range).
The slow way first
You might be tempted to reach for a big regular expression, or to scan the string character by character tracking dots and digits by hand. Both work, but they are easy to get subtly wrong — an off-by-one in the regex, a forgotten edge case in the manual scan.
The question to ask: what are the rules, exactly, and can I check them one at a time? There are only four: split on dots, get exactly four pieces, each piece is numeric, each piece is in range with no bad leading zero. Checking them in order is clear and hard to mess up.
The idea: split, then validate each part
Split the string on ".". If you do not get exactly four parts, it is invalid immediately. Then look at each part on its own and apply three small tests: it must be all digits, it must not have a leading zero (unless it is the single character "0"), and as a number it must be at most 255. If every part passes, the address is valid.
The key insight: each rule is independent. By turning the spec into a checklist and bailing out the moment any check fails, the logic stays flat and readable instead of one tangled condition.
Walk through it
Step through the animation. The string "192.168.0.1" splits into four boxes. The part pointer visits each one: 192, 168, 0, then 1. Each box lights up while we run the three checks, and turns green once it passes. Notice the 0 part — a lone zero is allowed, but "00" or "01" would be rejected by the leading-zero rule. After all four parts pass, we return True.
Pseudocode
parts = split s on "."
if number of parts is not exactly 4:
return False
for each part p in parts:
if p is not all digits:
return False
if p has more than one char and starts with "0":
return False # leading zero like "01"
if the number value of p is greater than 255:
return False
return True # all four parts passedThe Python solution
def is_valid_ipv4(s):
parts = s.split('.')
if len(parts) != 4:
return False
for p in parts:
if not p.isdigit():
return False
if len(p) > 1 and p[0] == '0':
return False
if int(p) > 255:
return False
return Trues.split('.')breaks the string into a list of parts on every dot.len(parts) != 4rejects anything that is not exactly four pieces — too few or too many dots.p.isdigit()rejects empty parts, signs, and any non-digit characters, so we knowint(p)is safe afterward.- The leading-zero check,
len(p) > 1 and p[0] == '0', blocks"01"or"00"while still allowing a single"0". int(p) > 255enforces the upper bound. We never check for a lower bound becauseisdigitalready guarantees the value is non-negative.
Complexity
| Case | Time | Notes |
|---|---|---|
| Split + per-part checks | O(n) (moderate) | n = length of the string |
| At most four parts | O(1) parts (fast) | each check is constant work |
O(n) (moderate)We touch each character a constant number of times, so the work is linear in the length of the string. The extra space is the list of parts produced by split, which is also O(n).
When this pattern shows up
When a problem hands you a formatted string — an IP address, a version number, a date, a file path — the reliable move is split on the delimiter, then validate each piece against the spec one rule at a time. Translate the written rules into a checklist of small conditions rather than one giant regex.
The leading-zero rule is the trap. "0" is valid but "00" and "01" are not, so you must allow a
single zero while rejecting a zero that prefixes other digits. Also remember to validate the part count
first — "1.1.1.1.1" has five parts and should fail before any range check runs.
Practice
For s = '192.168.01.1', which part fails and why?
1. Why do we check len(parts) != 4 before looking at the individual parts?
2. Why is the string '01' rejected but '0' accepted?
3. Why is there no explicit check that each part is at least 0?
4. What is the time complexity in terms of the string length n?