Restore IP Addresses
Problem statement
You get a string s made only of digits. Insert exactly three dots into it to form a valid IPv4 address, without adding, removing or reordering any digits. Return every address you can form, in any order.
Each of the four parts must be a number from 0 to 255 with no leading zero (a part can be 0, but not 00 or 01).
Examples
Example 1
Input: s = "11211"
Output: ["1.1.2.11", "1.1.21.1", "1.12.1.1", "11.2.1.1"]
Explanation: Five digits split into four parts means exactly one part has two digits, and every choice is valid.
Example 2
Input: s = "0100"
Output: ["0.1.0.0"]
Explanation: The only split into four parts is 0, 1, 0, 0. Any part like "01" or "00" would have a leading zero.
Hints
Approach
Backtracking with pruning. Build the address one part at a time. At each step try a part length of 1, 2 or 3, skip it if the part is invalid, and recurse on the rest of the string.
- If
shas fewer than 4 or more than 12 digits, return[]immediately. build(start, parts): if there are 4 parts, record the address only ifstart == n.- Prune: with
left = 4 - len(parts)parts still to place, the remainingn - startdigits must be betweenleftand3 * left. Otherwise return. - For each length 1 to 3: take the piece, stop if it has a leading zero or exceeds 255, and recurse.
There are at most 3 choices for each of 4 parts, so at most 81 paths, whatever the input. Once the length check passes, the work is bounded by a constant.
O(1)Space O(1)class Solution: def restoreIpAddresses(self, s: str) -> list[str]: n = len(s) result = [] if n < 4 or n > 12: return result def build(start: int, parts: list[str]) -> None: left = 4 - len(parts) if left == 0: if start == n: result.append(".".join(parts)) return if not left <= n - start <= 3 * left: # too few or too many digits remain return for length in (1, 2, 3): piece = s[start:start + length] if len(piece) < length: break if length > 1 and piece[0] == "0": # leading zero: longer pieces fail too break if int(piece) > 255: break parts.append(piece) build(start + length, parts) parts.pop() build(0, []) return resultFollow-up questions
- Return only the addresses that fall inside a private range such as
10.0.0.0/8or192.168.0.0/16. - Count the valid addresses without building the strings.
Frequently asked questions
A valid input has 4 to 12 digits, and longer or shorter strings are rejected before any search. Within that range the recursion has at most 3 choices at each of 4 levels, so the work has a fixed upper bound.
Pieces are tried shortest first. If a piece has a leading zero or is over 255, every longer piece from the same start has the same problem, so there is nothing left to try at this position.
It combines IPv4 rules, which network and platform engineers are expected to know cold, with a small, well-bounded backtracking search. It also invites a follow-up about recovering addresses from logs or exports where the dots were stripped.