Problem Statement
Restore IP Addresses
You are given a string s made only of digits, like "25525511135". Your job is to find every valid IP address you can make by slipping three dots into that string. An IP address is four numbers separated by dots, like 255.255.11.135. Each number, called a segment, has to follow two rules: it must be between 0 and 255, and it cannot have a leading zero (so "01" or "00" is not allowed, but plain "0" is fine). To solve this, we use backtracking. Backtracking means we try one choice, go deeper to see where it leads, and if it does not work out we undo that choice and try the next one. Think of walking a maze: you pick a path, and if you hit a dead end you back up to the last fork and try a different turn. Here, each "choice" is how many digits to grab for the next segment, 1, 2, or 3. Because an IP address always has exactly 4 segments and each segment is short, there are not many paths to try, so the work stays small.
Signals to notice
Brute force first
Try all 3 split points — O(n³).
The key insight
Backtracking: take 1-3 digits, validate (0-255, no leading zeros), recurse. 4 segments must consume all characters. O(1) since input ≤ 12 chars.
Trace it on s="101023"
backtrack(0,[]): try len1 seg="1" -> recurse start=1, segments=["1"] ["1","0"] at start=2: seg="10" -> ["1","0","10"] start=4, then "23" consumes all -> record "1.0.10.23"; seg="102" -> ["1","0","102"], "3" all -> record "1.0.102.3" ["1"] try len2 "01": leading zero -> break this branch ["10"] at start=2: "1"->["10","1","0"] then "23" -> record "10.1.0.23"; "10"->["10","10","2"] then "3" -> record "10.10.2.3"; "102"->"3" leaves only 3 segs at end -> dead ["101"] at start=3: "0"->["101","0","2"] then "3" -> record "101.0.2.3" len4 seg="1010" exceeds 3 digits / start+len>len(s) bounds -> loop ends, backtrack unwinds return ["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
What must stay true
Each segment: 1-3 digits, value 0-255, no leading zeros (except '0' alone). Exactly 4 segments consuming the full string.
Shape of the loop
backtrack(start, segments):
if len(segments)==4 and start==len(s): record '.'.join(segments); return
if len(segments)==4 or start==len(s): return
for length in 1..3:
if start + length > len(s): break # stay in bounds
seg = s[start:start+length]
if leadingZero(seg) or int(seg) > 255: break
backtrack(start+length, segments+[seg]) # then popPseudocode only — the full worked solution lives in the Solution tab.
Easy way to go wrong
Allowing '01' — only '0' is valid as a leading-zero segment.