Leetcode:93. Restore IP Addresses(Week1, Medium)

注:本題使用了分治的思想。
解題方法:遞歸法、暴力求解法


Leetcode 93
Given a string containing only digits, restore it by returning all possible valid IP address combinations.
For example:
Given “25525511135”,
return [“255.255.11.135”, “255.255.111.35”]. (Order does not matter)

  • 題意:

    • 給出一個字符串,然後你的程序需要解析出該字符串可能符合的所有合法ip地址並將之存儲在容器中。
  • 思路:

    • 先考慮合法ip地址的格式: “{0-255}.{0-255}.{0-255}.{0-255}”

    • ip地址由四個part和三個dot組成,每個part的位數爲1~3,每個part的值在0~255之間,且如果位數不是1位時,不能以0開頭,即不能存在011,01等情況。

    • 先採用分治的思想

    • 因爲ip地址是由四部分組成,每部分的構造與合法性要求是一致的,故我可以將分割字符串這個問題分成四個相同的小問題,然後採取遞歸的方式去解決它

    • 因爲有四個相同的小問題,很明顯,要得到一個合法的ip地址,需要執行四層遞歸 ,所以需要傳入參數n來標識進行到第幾層遞歸。

    • 然後需要傳入未切割的字符串、存儲當前遞歸得到的合法ip地址(一個)的String變量、還有存儲所有合法ip地址的vector容器

    • 因爲對於每一個部分,有三種情況切割,即1位、2位、3位,故在遞歸函數中定義一層for循環用於分類討論,然後將各種分割情況的剩餘字符串傳入下一層遞歸函數中

    • 代碼如下:

      /*2017/9/10 93. Restore_IP_Address 的遞歸寫法(分治思想)
      思路:
      1.ip地址是四個部分,即需要將字符串切割成四部分;
      2.需要對每一部分進行分類討論,即每部分是1位、2位或者是3位,且要對每一部分的合法性進行驗證,故
        可以將問題分解成四個相同的小部分,然後用遞歸實現;
      3.在每一次的遞歸中,由於需要分類討論,所以還需要一層for循環。
      */
      
      class Solution {
      public:
          vector<string> restoreIpAddresses(string s) {
              vector<string> result;
              Calc(0, s, result, "");
              return result;
          }
          /*
          @func Calc:處理每部分part的遞歸函數
          @param n:遞歸層數
          @param s:切割後剩餘字符串
          @param result: 存儲所有合法ip地址的容器
          @param output: 存儲當前遞歸合法ip地址的變量*/
          void Calc(int n, string s, vector<string>& result, string output) { // result 記得加&
              // n == 0,1,2,3 分別代表第一、二、三、四層遞歸
              // n == 4 用於終止遞歸,如果s爲空,說明分割準確
              if (n == 4) {
                  if (s.empty()) result.push_back(output);
              } else {
                  for (int k = 1; k <= 3; k++) {
                      // 如果剩餘字符串不足以分割,則分割不合法
                      if (s.size() < k) break;
                      int val = atoi(s.substr(0, k).c_str());
                      // 當出現以0開頭的part,如011, k != std::to_string(val).size()
                      if (val <= 255 && k == std::to_string(val).size()) {
                          Calc(n+1, s.substr(k), result, output+s.substr(0, k)+(n == 3? "" : "."));
                      }
                  }
              }
          }
      };
  • 補充,由於分割情況不多,這道題可以使用暴力求解法。

    • 假設四個部分的長度分別爲a,b,c,d, 那麼我可以用四層循環得出所有分割組合,即滿足a+b+c+d = s.size(),然後分別檢測所有分割組合的合法性,將合法的存入vector容器中

    • 代碼如下:

      /*
      2017/9/10 93. Restore_IP_Address 的遞歸寫法(暴力求解)
      思路:
      ip地址分成四部分,每部分的長度最大爲3,這個數字很小,
      要得到所有情況,可用暴力求解法
      即四層for循環,得到所有符合的組合 a+b+c+d = s.size()
      然後對組合分別進行檢驗,將符合的加入到容器中
      */
      
      class Solution {
      public:
          vector<string> restoreIpAddresses(string s) {
              vector<string> result;
              string output;
              for (int a = 1; a <= 3; a++) {
                  for (int b = 1; b <= 3; b++) {
                      for (int c = 1; c <= 3; c++) {
                          for (int d = 1; d <= 3; d++) {
                              if (a+b+c+d == s.size()) {
                                  int A = atoi(s.substr(0, a).c_str());
                                  int B = atoi(s.substr(a, b).c_str());
                                  int C = atoi(s.substr(a+b, c).c_str());
                                  int D = atoi(s.substr(a+b+c).c_str());
                                  if (A <= 255 && B <= 255 && C <= 255 && D <= 255) {
                                      output = std::to_string(A) + "."
                                              + std::to_string(B) + "."
                                              + std::to_string(C) + "."
                                              + std::to_string(D);
                                      // 如果有一個part出現以0開頭的,如011,
                                      // 那麼output.size()!=s.size() + 3
                                      if (output.size() == s.size() + 3)
                                          result.push_back(output);
                                  }
                              }
                          }
                      }
                  }
              }
              return result;
          }
      };

以上內容皆爲本人觀點,歡迎大家提出批評和指導,我們一起探討!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章