---
# System prepended metadata

title: 'LeetCode #93 [Restore IP Addresses](https://leetcode.com/problems/restore-ip-addresses/)'
tags: [DFS, LeetCode, Medium, String]

---

###### tags: `LeetCode` `Medium` `DFS` `String`
# LeetCode #93 [Restore IP Addresses](https://leetcode.com/problems/restore-ip-addresses/) 
### (Medium)

給定一個只包含數字的字符串，用以表示一個 IP 地址，返回所有可能從 s 獲得的 有效 IP 地址 。你可以按任何順序返回答案。

有效 IP 地址 正好由四個整數（每個整數位於 0 到 255 之間組成，且不能含有前導 0），整數之間用 '.' 分隔。

例如："0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址，但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 無效 IP 地址。

---
由於IPv4地址每格為0~255, 也就是1~3位數, 因此需分別考慮每位數並呼叫遞迴。

首先, 若給定字串長度小於4(4個1)或大於12(4個3)則直接返回空集合。使用計數器統計目前已完成幾個ip字節(總共4個), 當ip字節數等於4, 且ip位置等於原自串長度+3(新增3個'.')則將該ip加到答案數組中(合法ip)。

要注意的點:
1. substr的使用:與java的substring不同, C++的參數為 目標字串.substr(起始位置, 要從起始位置開始切割多少長度), 也就是說s.substr(4,2)代表從第4個字元開始往後數兩個, 也就是s[5], s[6]這兩個字元。而java的substring則是 目標字串.substring(起始位置, 終止位置)。
2. 若切割出來的ip字節長度大於1, 則不能為0開頭, 比如說: 012、01...等是非法的ip字節。
3. 當處理到第四個字節時不需要再加'.', 所以要一個額外判斷式負責決定。

---
```
class Solution {
public:
    vector<string> restoreIpAddresses(string s) {
        vector<string> ans;
        if(s.size()>12||s.size()<4)return {};
        dfs(0, s, 0, "", ans);
        return ans;
    }
    void dfs(int index, const string& s, int times, string tmp, vector<string>& ans){
        if(times==4){
            if(tmp.length()==s.length()+3)
                ans.push_back(tmp);
            return;
        }
        for(int i=1;i<=3;i++){
            if(index+i>s.size())break;
            string subs = s.substr(index, i);
            if(subs.length()>1&&subs[0]=='0')continue;
            if(stoi(subs)<=255)
                dfs(index+i, s, times+1, tmp+subs+(times==3?"":"."), ans);
        }
    }
};
```