如果 s.size() > 12 或者 < 4, 直接 return, 这个无话可说..
然后就是枚举三个点的位置, 判断每个部分是否含前缀 0 和是否小于 255 即可。
如,第一部分只可能是 下标为 i ∈ [0, 2],然后第二部分则为 j ∈ [i + 1, i + 3],第四部分为 k ∈ [sz - 3, sz - 1],第三部分则是剩余的。
然后其实这样枚举可能出现越界的问题,比如给出字符串总长度为 4, i 的边界实际上到不了 2。但是不在 for 循环范围中处理边界,使用计算这个部分的大小来判断是否合法,即代码中的 sz1, sz2, sz3, sz4.
class Solution { public: vector<string> restoreIpAddresses(const string &s) { if(s.size() > 12 || s.size() < 4) return {}; vector<string> ret; int sz = s.size(); for(int i = 0; i <= 2; ++ i) { // [0, i] 第一部分 for(int j = i + 1; j <= i + 3; ++ j) { // [i + 1, j] 为第二部分 for(int k = sz - 1; k >= sz - 3; -- k) { // [k, sz - 1] 为第四部分, [j + 1, k - 1] 为第三部分 int sz1 = i + 1, sz2 = j - (i + 1) + 1; int sz3 = (k - 1) - (j + 1) + 1, sz4 = sz - 1 - k + 1; if(!check(s, 0, sz1) || !check(s, i + 1, sz2) || !check(s, j + 1, sz3) || !check(s, k, sz4)) continue; string tmp; insert(s, tmp, 0, sz1); tmp.push_back(‘.‘); insert(s, tmp, i + 1, sz2); tmp.push_back(‘.‘); insert(s, tmp, j + 1, sz3); tmp.push_back(‘.‘); insert(s, tmp, k, sz4); ret.emplace_back(std::move(tmp)); } } } return ret; } private: bool check(const string &s, int i, int sz) { if(sz <= 0) return false; if(sz > 1 && s[i] == ‘0‘) return false; // 前导 0 int num = 0; for(int j = i; j < i + sz; ++ j) { num = num * 10 + (s[j] - ‘0‘); } return num <= 255; } void insert(const string &s, string &tmp, int i, int sz) { for(int j = i; j < i + sz; ++ j) { tmp.push_back(s[j]); } } };