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;
          }
      };

以上内容皆为本人观点,欢迎大家提出批评和指导,我们一起探讨!


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