切割问题

leetcode 131.分割回文串

  • 组合问题:选取一个a之后,在bcdef中再去选取第二个,选取b之后在cdef中在选组第三个.....。
  • 切割问题:切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中在切割第三段.....。

把切割问题转换为树形结构

如何模拟切割线?
如何截取子串?

我们用startindex来模拟切割线

for (int i = startIndex; i < s.size(); i++)先判断是不是回文,[startindex,1]就是要截取的子串

判断回文子串

bool isPalindrome(const string& s, int start, int end) {
 for (int i = start, j = end; i < j; i++, j--) {
     if (s[i] != s[j]) {
         return false;
     }
 }
 return true;
}
  • 中止条件

      if (startIndex >= s.size()) {//起始位置大于s的大小,说明找到一组分割方案
      result.push_back(path);
      return;
      }
    
  • 单层搜索逻辑

      for (int i = startIndex; i < s.size(); i++) {
      if (isPalindrome(s, startIndex, i)) { // 是回文子串
          // 获取[startIndex,i]在s中的子串
          string str = s.substr(startIndex, i - startIndex + 1);
          path.push_back(str);
      } else {                // 如果不是则直接跳过
          continue;
      }
      backtracking(s, i + 1); // 寻找i+1为起始位置的子串
      path.pop_back();        // 回溯过程,弹出本次已经填在的子串
      }
    
  • 回溯函数参数与返回值

    void backtracking (const string& s, int startIndex)

C++整体代码

class Solution {
private:
vector<vector<string>> result;
vector<string> path; // 放已经回文的子串
void backtracking (const string& s, int startIndex) {
    // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
    if (startIndex >= s.size()) {
        result.push_back(path);
        return;
    }
    for (int i = startIndex; i < s.size(); i++) {
        if (isPalindrome(s, startIndex, i)) {   // 是回文子串
            // 获取[startIndex,i]在s中的子串
            string str = s.substr(startIndex, i - startIndex + 1);
            path.push_back(str);
        } else {                                // 不是回文,跳过
            continue;
        }
        backtracking(s, i + 1); // 寻找i+1为起始位置的子串
        path.pop_back(); // 回溯过程,弹出本次已经填在的子串
    }
}
bool isPalindrome(const string& s, int start, int end) {
    for (int i = start, j = end; i < j; i++, j--) {
        if (s[i] != s[j]) {
            return false;
        }
    }
    return true;
}
public:
vector<vector<string>> partition(string s) {
    result.clear();
    path.clear();
    backtracking(s, 0);
    return result;
}
};

leetcode 93.复原IP地址

思路及分析

先判断字符的长度,小于4或大于16,一定不能成为IP地址,只能插入3个点号,所以递归树的深度为4

本题的树形结构

  • 确定回溯函数的参数及返回值
    递归中止需要判断逗号的个数,所以传入点号的个数,不能去重复元素,所以要传入下一次开始的下标

    void backtracking(int startindex,pushpoint,s);

  • 递归中止条件

当逗号的个数为3时,判断最后一段能否组成合法的ip数字

if(3 == pushpoint){
        if(judge(s,startindex,s.size() - 1)){
            result.push_back(s);
        }
        return;
    }
  • 单层回溯搜索逻辑

先判断能否组成合法的ip数字,再插入点号, 下一层递归的startIndex要从i+2开始

for(int i = startindex; i < s.size();i++){
        if(judge(s,startindex,i)){
            s.insert(s.begin() + i + 1,'.');
            backtracking(i + 2,pushpoint + 1,s);
            s.erase(s.begin() + i + 1);
        } else{
            break;
        }
    }
  • 判断子串是否合法

         bool judge(const string& s, int start, int end) {
          if (start > end) {
              return false;
          }
          if (s[start] == '0' && start != end) { // 0开头的数字不合法
                  return false;
          }
          int num = 0;
          for (int i = start; i <= end; i++) {
              if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
                  return false;
              }
              num = num * 10 + (s[i] - '0');
              if (num > 255) { // 如果大于255了不合法
                  return false;
              }
          }
          return true;
      }
    

C++完整代码

class Solution {
public:
vector<string> result;
bool judge(const string& s, int start, int end) {
if (start > end) {
    return false;
}
if (s[start] == '0' && start != end) { // 0开头的数字不合法
        return false;
}
int num = 0;
for (int i = start; i <= end; i++) {
    if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法
        return false;
    }
    num = num * 10 + (s[i] - '0');
    if (num > 255) { // 如果大于255了不合法
        return false;
    }
}
return true;
}

void backtracking(int startindex,int pushpoint,string& s){
    if(pushpoint == 3){
        if(judge(s,startindex,s.size() - 1)){
            result.push_back(s);
        }
        return;
    }
    for(int i = startindex; i < s.size();i++){
        if(judge(s,startindex,i)){
            s.insert(s.begin() + i + 1,'.');
            backtracking(i + 2,pushpoint + 1,s);
            s.erase(s.begin() + i + 1);
        } else{
            break;
        }
    }
}
vector<string> restoreIpAddresses(string s) {
    int pushpoint = 0;
    if(s.size() < 4 || s.size() > 16) return result;
    backtracking(0,0,s);
    return result;
}

};

posted @ 2022-10-13 22:17  WetYu  阅读(5)  评论(0)    收藏  举报