LeetCode Restore IP Addresses:給定純數字字串,插入 3 個點分成 4 段,每段 0-255 且無前導零(除非單個 0),返回所有合法 IP 地址。
void dfs(int seg, int idx, string& s, string& path, vector<string>& res) {
if (seg == 4) {
if (idx == s.size()) res.push_back(path.substr(0, path.size()-1)); // 去掉末尾 '.'
return;
}
if (idx == s.size()) return; // 字串用盡但段數不足
// 嘗試長度 1,2,3
for (int len = 1; len <= 3 && idx + len <= s.size(); ++len) {
string part = s.substr(idx, len);
if (valid(part)) {
int old_len = path.size();
path += part + '.';
dfs(seg + 1, idx + len, s, path, res);
path.resize(old_len); // 回溯
}
}
}
bool valid(const string& s) {
if (s[0] == '0') return s == "0"; // 前導零檢查
int val = stoi(s);
return val > 0 && val <= 255;
}
class Solution {
public:
vector<string> restoreIpAddresses(string s) {
vector<string> res;
if (s.size() < 4 || s.size() > 12) return res;
string path;
dfs(0, 0, s, path, res);
return res;
}
private:
void dfs(int seg, int idx, const string& s, string& path, vector<string>& res) {
if (seg == 4) {
if (idx == s.size()) res.push_back(path.substr(0, path.size()-1));
return;
}
if (idx == s.size()) return;
for (int len = 1; len <= 3 && idx + len <= s.size(); ++len) {
// 前導零快速剪枝
if (len > 1 && s[idx] == '0') break;
int val = 0;
for (int i = 0; i < len; ++i)
val = val * 10 + (s[idx+i] - '0');
if (val > 255) break; // 單調遞增,後續更大
int old = path.size();
path.append(s, idx, len);
path.push_back('.');
dfs(seg + 1, idx + len, s, path, res);
path.resize(old);
}
}
};
len>1 && s[idx]=='0' → breakval > 255 → break(後續長度更大)4 ≤ n ≤ 12 直接返回空public class Solution {
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<>();
if (s == null || s.length() < 4 || s.length() > 12) return res;
StringBuilder path = new StringBuilder();
dfs(0, 0, s, path, res);
return res;
}
void dfs(int seg, int idx, String s, StringBuilder path, List<String> res) {
if (seg == 4 && idx == s.length()) {
res.add(path.substring(0, path.length()-1));
return;
}
if (seg == 4 || idx == s.length()) return;
for (int len = 1; len <= 3 && idx + len <= s.length(); len++) {
if (len > 1 && s.charAt(idx) == '0') break;
int val = Integer.parseInt(s.substring(idx, idx+len));
if (val > 255) break;
int old = path.length();
path.append(s, idx, idx+len).append('.');
dfs(seg+1, idx+len, s, path, res);
path.setLength(old);
}
}
}
此題是回溯算法入門的完美範例,展示了約束傳播、剪枝優化與工程級代碼實現的結合。