每天一道LeetCode-----将字符串拆分成有效的ip地址
Restore IP Addresses
原題鏈接Restore IP Addresses
給定一個僅包含數(shù)字的字符串,將其拆分成有效的ip地址
題目的主要意思實際是在字符串中添加三個點,從而構(gòu)成一個ip地址,有效的ip地址格式為
- 最多包含12個數(shù)字
- 每個數(shù)字在[0, 255]之間
- 數(shù)字中除了單一0,不能出現(xiàn)類似0開頭的數(shù)字,比如192.168.1.013中013是不允許的
所以其實就是隨便找到三個位置,判斷拆分成的四塊數(shù)字是否滿足要求即可
首先,為了易于理解,在安插”.”的過程中不記錄組成的ip地址,只是將”.”的位置記錄下來,當(dāng)”.”的個數(shù)為3時統(tǒng)一計算
代碼如下
class Solution { public:vector<string> restoreIpAddresses(string s) {vector<string> res;//不合法if(s.size() > 12) return res;//記錄"."的位置vector<int> dots;dfs(s, res, dots, 0);return res;} private:void dfs(string& s, vector<string>& res, vector<int>& dots, int idx){if(dots.size() == 3){//判斷四個數(shù)字是否符合要求,然后添加//計算one時的寫法是有原因的,可以將dots[-1] 看做 -1string one = s.substr(-1 + 1, dots[0] - (-1));string two = s.substr(dots[0] + 1, dots[1] - dots[0]);string three = s.substr(dots[1] + 1, dots[2] - dots[1]);string four = s.substr(dots[2] + 1);if(isValid(one) && isValid(two) && isValid(three) && isValid(four))res.emplace_back(one + "." + two + "." + three + "." + four);return;}//因為最后一個"."后面必須有數(shù)字,所以到s.size() - 1即可for(int i = idx; i < static_cast<int>(s.size()) - 1; ++i){//表示將"."放在s[i]的后面dots.emplace_back(i);dfs(s, res, dots, i + 1);dots.pop_back();}}bool isValid(string numStr){if(numStr.size() > 3 || (numStr.size() > 1 && numStr.find_first_not_of('0') != 0) || (numStr.size() == 3 && numStr > "255"))return false;elsereturn true;} };這種方法比較慢,主要的原因是會將所有可能都找出來然后判斷是否合法,也就是說當(dāng)確定第一個”.”的位置時,這個位置可能是不合適的,但是仍然需要進(jìn)行到最后
深度優(yōu)先和回溯法的思想在于將不合法的情況扼殺在搖籃里,也就是要確定”.”的位置時判斷是否滿足要求,如果不滿足要求,就沒必要按照這個”.”的位置進(jìn)行下去
所以,需要在for循環(huán)中動手腳,判斷”.”的位置是否合適。方法就是判斷當(dāng)前這個”.”和上一個”.”之間的數(shù)字是否符合要求,這里用prevIdx變量記錄上一個”.”的位置
由上面計算one,two,three,four的公式可知,兩個”.”之間的數(shù)字正是[prevIdx+1, i],其中
- prevIdx記錄上一個”.”的位置,初始時為-1,類似公式中的dots[0]
- i是當(dāng)前要確定的”.”的位置,指在s[i]后面插入”.”,類似公式中的dots[1]
有了上面的基礎(chǔ),代碼可以更改為
class Solution { public:vector<string> restoreIpAddresses(string s) {vector<string> res;//不合法if(s.size() > 12) return res;//記錄"."的位置vector<int> dots;dfs(s, res, dots, -1, 0);return res;} private:void dfs(string& s, vector<string>& res, vector<int>& dots, int prevIdx, int idx){if(dots.size() == 3){//判斷四個數(shù)字是否符合要求,然后添加//計算one時的寫法是有原因的,可以將dots[-1] 看做 -1string one = s.substr(-1 + 1, dots[0] - (-1));string two = s.substr(dots[0] + 1, dots[1] - dots[0]);string three = s.substr(dots[1] + 1, dots[2] - dots[1]);string four = s.substr(dots[2] + 1);//one two three在確定"."時已經(jīng)判斷過if(isValid(four))res.emplace_back(one + "." + two + "." + three + "." + four);return;}//因為最后一個"."后面必須有數(shù)字,所以到s.size() - 1即可for(int i = idx; i < static_cast<int>(s.size()) - 1; ++i){//判斷是否滿足要求if(!isValid(s.substr(prevIdx + 1, i - prevIdx)))return;//表示將"."放在s[i]的后面dots.emplace_back(i);dfs(s, res, dots, i, i + 1);dots.pop_back();}}bool isValid(string numStr){if(numStr.size() > 3 || (numStr.size() > 1 && numStr.find_first_not_of('0') != 0) || (numStr.size() == 3 && numStr > "255"))return false;elsereturn true;} };再簡單一點,可以不需要dots,在遍歷的過程中就將最后的ip地址構(gòu)造好
class Solution { public:vector<string> restoreIpAddresses(string s) {vector<string> res;//不合法if(s.size() > 12) return res;string cur("");dfs(s, res, cur, -1, 0, 0);return res;} private:void dfs(string& s, vector<string>& res, string& cur, int prevIdx, int idx, int count){if(count == 3){string four = s.substr(idx);if(isValid(four))res.emplace_back(cur + four);return;}//因為最后一個"."后面必須有數(shù)字,所以到s.size() - 1即可string tmp = cur;for(int i = idx; i < static_cast<int>(s.size()) - 1; ++i){//判斷是否滿足要求if(!isValid(s.substr(prevIdx + 1, i - prevIdx)))break;cur.append(1, s[i]);cur.append(1, '.');dfs(s, res, cur, i, i + 1, count + 1);//回溯的過程需要回到原來的樣子,但是這里只彈出了"."的目的是為了繼續(xù)擴(kuò)充當(dāng)前數(shù)字//不需要回到append(1, s[i])之前的樣子,但是return之前需要cur.pop_back();}//當(dāng)返回時回到原來的樣子std::swap(cur, tmp);}bool isValid(string numStr){if(numStr.size() > 3 || (numStr.size() > 1 && numStr.find_first_not_of('0') != 0) || (numStr.size() == 3 && numStr > "255"))return false;elsereturn true;} };本題主要思路是在s中選擇三個位置作為”.”,同時確定分出的四個數(shù)字是否合法
總結(jié)
以上是生活随笔為你收集整理的每天一道LeetCode-----将字符串拆分成有效的ip地址的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一道LeetCode-----逆序链
- 下一篇: 每天一道LeetCode-----实现二