Restore IP Addresses
Problem Statement
Given a string s containing only digits, return all possible valid IP addresses that can be formed by inserting exactly three dots. A valid IP address has exactly four integer segments, each segment is between 0 and 255, and a segment cannot have leading zeroes unless it is exactly 0.
Input
A digit string s with no dots already placed.
Output
A list of valid IP address strings in any order.
Constraints
- •
1 <= s.length <= 20 - •
s consists of digits only
Examples
Example 1
s = 25525511135
[255.255.11.135,255.255.111.35]Example 2
s = 0000
[0.0.0.0]Example 3
s = 101023
[1.0.10.23,1.0.102.3,10.1.0.23,10.10.2.3,101.0.2.3]Learning Objectives
- Recognise IP restoration as a constrained **choose a segment, recurse on the suffix** problem.
- Use segment count and start index as the recursion state.
- Prune by remaining length before trying segment values.
- Validate each segment with length, leading-zero, and numeric range checks.
Intuition
Pattern Recognition
This is another cut and partition string problem, but the partition must have exactly four pieces. At each frame, choose the next segment length: 1, 2, or 3 digits. If that segment is valid, append it and recurse on the remaining suffix.
The constraints make pruning especially important. With k segments left, the remaining character count must be at least k and at most 3k. A segment like 01 is invalid before numeric parsing because of the leading zero rule, and a segment like 256 is invalid because it exceeds 255. The base case succeeds only when exactly four segments have been chosen and the entire string has been consumed.
Common mistakes
- ×Accepting segments with leading zeroes such as **01** or **00**.
- ×Recording an address after four segments even when some input digits remain unused.
- ×Trying segment lengths beyond three digits and then relying on numeric checks alone.
- ×Forgetting to remove the last chosen segment before trying the next sibling cut.
Algorithm Explanation
State
Each frame carries start, the next unconsumed character index, and segments, the list of chosen IP pieces so far. The number of remaining segments is 4 - segments.size(). A valid branch must eventually consume every character exactly once.
Recursion tree
For s = 101023, the root may choose 1, 10, or 101 as the first segment. Under first segment 1, the next character is 0, so the only valid second segment starting there is 0; candidates 01 and 010 are pruned by the leading-zero rule. From [1,0], choices 1, 10, and 102 lead to different suffixes. The branch [1,0,10,23] consumes the string and records 1.0.10.23, while a branch such as [1,0,1,0] has characters left after four segments and is rejected.
Pruning
Before trying a segment, compare the remaining characters with the remaining segment slots. If there are too few characters to give every slot one digit, or too many characters to fit into three digits per slot, return immediately. For each candidate segment, reject lengths greater than 3, multi-character segments starting with 0, and numeric values above 255.
Algorithm
- Start DFS with start = 0 and an empty segment list.
- Compute remaining characters and remaining segment slots; return if the length bounds cannot be satisfied.
- If four segments have been chosen, record an address only when start == s.length.
- Try segment lengths 1, 2, and 3 while staying inside the string.
- Reject a segment if it has a leading zero or if Integer.parseInt gives a value above 255.
- Append the valid segment, recurse from the next start index, then remove it.
- Build an address from four segments by joining them with the plain . character.
Solutions
Solution: Four-segment DFS with validity pruning
The DFS places one IP segment at a time. Because an IP address always has four segments and each segment has length 1 through 3, the branching factor is tiny; correctness comes from strict pruning of invalid segment shapes and from accepting only branches that consume the whole string.
Step-by-step
- Track the current index and the list of chosen segments.
- Use remaining-character bounds to stop branches that cannot possibly fill the remaining slots.
- If four segments are chosen, add an address only when the index is at the end of the string.
- Try segment lengths from 1 through 3.
- Validate leading zeroes and the numeric value 0 <= value <= 255.
- Choose the segment, recurse, and unchoose it before trying the next length.
O(3^4)
O(1)
There are at most 3 length choices for each of 4 segments. Auxiliary space is constant because recursion depth and path size are bounded by 4, excluding output.
Java implementation
Dry Run
Sample input
s = 101023. Track segment choices, leading-zero pruning, and the requirement that four segments must consume the whole string.
| depth | start | segment | path | action |
|---|---|---|---|---|
| 0 | 0 | 1 | [1] | valid first segment, recurse from 1 |
| 1 | 1 | 0 | [1,0] | single zero is allowed, recurse from 2 |
| 2 | 2 | 1 | [1,0,1] | valid third segment, recurse from 3 |
| 3 | 3 | 0 | [1,0,1,0] | four segments chosen but characters remain, prune |
| 3 | 3 | 02 | [1,0,1] | leading zero, prune |
| 2 | 2 | 10 | [1,0,10] | valid third segment, recurse from 4 |
| 3 | 4 | 23 | [1,0,10,23] | consumed whole string, record 1.0.10.23 |
| 2 | 2 | 102 | [1,0,102] | valid third segment, recurse from 5 |
| 3 | 5 | 3 | [1,0,102,3] | consumed whole string, record 1.0.102.3 |
| 1 | 1 | 01 | [1] | leading zero, prune sibling segment |
| 0 | 0 | 10 | [10] | valid first segment, explore another branch |
| 0 | 0 | 101 | [101] | valid first segment, explore another branch |
The DFS records only branches with four valid segments and no leftover characters. Leading-zero pruning removes many tempting but invalid cuts after a 0 digit.
Interview Tips
Name all three validity rules before coding: length at most three, numeric value at most 255, and no leading zero unless the segment is exactly 0. Then add the remaining-length bound because it demonstrates pruning maturity and prevents exploring branches that cannot fill exactly four segments.
Likely follow-ups
- How would you adapt the method for IPv6-style groups with hexadecimal characters?
- How would you return only the count of valid addresses?
- How would the pruning change if the number of required segments were a parameter?
- How would you validate a string that already contains dots instead of inserting them?
Similar Problems
Key Takeaways
- Restore IP Addresses is fixed-depth string partitioning with aggressive validity pruning.
- The base case requires both four segments and full input consumption.
- Leading zeroes must be rejected before accepting a multi-character segment.
- Remaining-length bounds are a simple way to cut impossible branches early.