自己写的
class Solution { public: vector<string> restoreIpAddresses(string s) { // 先排除一波 vector<string> ret; if (s.size() > 4 * 3 || s.size() < 4) return ret; // 再排除一下不全是数字的 if (!isNum(s)) return ret; ret = restoreIpAddressesHelper(s, s.size(), 4); return ret; } private: vector<string> restoreIpAddressesHelper(const string s, const int strlen, const int count) { vector<string> ret; if (count < 1 || strlen > count * 3 || strlen < count) return ret; if (count == 1) { int i = -1; // 第一位不能是0 if (strlen > 1 && s[0] == '0') return ret; // 如果只有3位 看是否符合要求 if (strlen == 3) { i = convertStringToInt(string(s, 0, 3)); if (i > 255) { return ret; } } string str = string(s, 0, strlen) + '.'; ret.push_back(str); } else { bool needPoint = true; if (count == 4) { needPoint = false; } for (int i = 1; i <= 3 && strlen >= i; ++i) { string strCur = string(s, strlen - i, i); if (i != 1 && s[strlen - i] == '0') { continue; } if (i == 3) { if (convertStringToInt(strCur) > 255) continue; } vector<string> retTmp = restoreIpAddressesHelper(s, strlen - i, count - 1); for (int j = 0; j < retTmp.size(); ++j) { string strAppend = needPoint ? retTmp[j] + strCur + '.' : retTmp[j] + strCur; ret.push_back(strAppend); } } } return ret; } bool isNum(string s) { if (s.empty()) return false; for (int i = 0; i < s.size(); ++i) { if (s[i] < '0' || s[i] > '9') return false; } return true; } int convertStringToInt(const string &s) { int val; std::stringstream ss; ss<<s; ss>>val; return val; } };
注意点:
1. stringstream 类所在头文件 <sstream>
2. bug:没有判断 strlen - i 是否大于等于0。导致数组越界。
string strCur = string(s, strlen - i, i);
leetcode上的示例:
class Solution1 { public: vector<string> restoreIpAddresses(string s) { vector<string> res; vector<string> tmp; int count = 0; int n = s.length(); solve(res, tmp, s, 0, 0, n); return res; } // res 存的 是每次找到的有效的最终 ip 地址,即结果 // tmp 存的 某次查找的时候 ,每个 ip 段,最终ip 由 四段组成。 // s 即输入字符串一直没变 // count 表示当前 tmp 中的 ip段 个数 // start 表示 从s的位置索引开始找有效ip部分 // n 表示 s的长度 一直不变 void solve(vector<string>& res, vector<string>& tmp, string& s, int count, int start, const int n) { if (count == 4) { if (start == n) { string t = ""; for (int i = 0; i < 3; i++) { t += tmp[i] + "."; } t += tmp[3]; res.push_back(t); } return; } if (start == n) { return; } for (int i = start; i < n; i++) { if (i + 1 - start > 3) { return; } string t = string(s.begin() + start, s.begin() + i + 1); if (t.length() > 1 && t[0] == '0') { return; } int e = stoi(t); if (e <= 255) { count++; tmp.push_back(t); solve(res, tmp, s, count, i + 1, n); count--; tmp.pop_back(); } } } };
分析:
1.从前往后找,使用tmp进行暂存,如果已经找到四个ip段了,看是否正好走完string,如果是就存入res,否则不存入。使用回溯的方法进行继续查找。
2.int e = stoi(t); string转int的函数。 C++11中的增加的。
3.string t = string(s.begin() + start, s.begin() + i + 1); 使用迭代器进行初始化
template <class InputIterator> string (InputIterator first, InputIterator last);