93. Restore IP Addresses
MediumDescription
給定一個只包含數字的字串
s,回傳所有可能的合法 IPv4 地址。合法 IP 地址由四個 0 到 255 的整數組成,用 ‘.’ 分隔,且整數不能有前導零(除了 “0” 本身)。
Example:
Input: s = “25525511135” Output: [“255.255.11.135”,“255.255.111.35”]
Intuition#
核心思路:回溯法在字串中嘗試放置 3 個分隔點,每段需滿足 IP 地址規則。
- IP 地址有 4 段,每段 1
3 個字元,值在 0255 之間,無前導零 - 回溯:每次嘗試切 1~3 個字元作為一段,驗證合法性後遞迴
- 當已切出 4 段且剛好用完所有字元時,收集結果
Approaches#
⭐1: 回溯法#
- 概念: 遞迴嘗試每段取 1~3 位數,驗證合法性,切滿 4 段且字串用完即為合法結果
- 時間複雜度:
O(3^4)=O(81)- 每段最多 3 種切法,共 4 段 - 空間複雜度:
O(1)- 固定深度 4
class Solution {
fun restoreIpAddresses(s: String): List<String> {
val result = mutableListOf<String>()
val segments = mutableListOf<String>()
fun backtrack(start: Int) {
if (segments.size == 4) {
if (start == s.length) {
result.add(segments.joinToString("."))
}
return
}
for (len in 1..3) {
if (start + len > s.length) break
val segment = s.substring(start, start + len)
// 前導零檢查:長度 > 1 但以 '0' 開頭
if (segment.length > 1 && segment[0] == '0') break
// 範圍檢查
if (segment.toInt() > 255) break
// 剩餘長度檢查
val remaining = s.length - start - len
val segmentsLeft = 3 - segments.size
if (remaining < segmentsLeft || remaining > segmentsLeft * 3) continue
segments.add(segment)
backtrack(start + len)
segments.removeAt(segments.lastIndex)
}
}
backtrack(0)
return result
}
}🔑 Takeaways#
- Pattern: 字串分割問題 → 回溯法逐段切割並驗證
- 關鍵技巧: 三個驗證條件(前導零、範圍 0-255、剩餘長度足夠);因為 IP 固定 4 段且每段最多 3 位,搜索空間極小(常數級)。類似 131. Palindrome Partitioning 的分割策略