Day24:93.复原IP地址、78.子集、90.子集II

93.复原IP地址


题目链接

思路

子串分割问题:
第一反应是用组合思路分割字符串再放入path路径最后放入result结果集,但是操作有点繁琐,只需插入分割点‘.’即可解决。

  1. 分割子串
    startIndex记录子串起始位置,for循环向后遍历,取不同长度子串。
        for (int i = startIndex; i < s.size(); i++) {}
  1. 循环终止条件
    当已经插入三个‘.’,此时只需要判断留下的最后一个子串是否符合条件。
        if (pointNum == 3) { 
            if (isValid(s, startIndex, s.size() - 1)) {
                result.push_back(s);
            }
            return;
        }
  1. 递归回溯操作
    先判断当前分割出的子串是否符合条件
    符合条件则可以在分割的子串后插入分割点,然后继续向后递归。回溯操作即为撤销插入的分割点
    不符合条件则终止当前循环,继续分割新的子串
    if (isValid(s, startIndex, i)) { 
                s.insert(s.begin() + i + 1 , '.');
                pointNum++;
                backtracking(s, i + 2); 
                pointNum--;         
                s.erase(s.begin() + i + 1);        
            } else break; 
        }
  1. 判断子串是否符合条件
    传入的参数为字符串s,起始位置start,终止位置end
    1. 当start>end,不符合条件
    2. 当字符串以0为起始,即s[start]=‘0’&&start!=end,不符合条件
    3. 当字符串内有不合法字符,不符合条件
    4. 当字符串表示数值大于255,不符合条件
    bool isValid(const string& s, int start, int end) {
        int num=0;
        if(start>end)return false;
        if(s[start]=='0'&&start!=end)return false;
        for(int i=start;i<=end;i++){
            if(s[i]<'0'||s[i]>'9')return false;
            num*=10;
            num+=s[i]-'0';
            if(num>255)return false;
        }
        return true;        
    }
  1. 剪枝
    当字符串长度大于12或者小于4时,肯定是不合法的IP地址
        if (s.size() < 4 || s.size() > 12) return result;

代码实现

class Solution {
private:
    vector<string> result;
    int pointNum=0;
    void backtracking(string& s, int startIndex ) {
        if (pointNum == 3) { 
            if (isValid(s, startIndex, s.size() - 1)) {
                result.push_back(s);
            }
            return;
        }
        for (int i = startIndex; i < s.size(); i++) {
            if (isValid(s, startIndex, i)) { 
                s.insert(s.begin() + i + 1 , '.');
                pointNum++;
                backtracking(s, i + 2); 
                pointNum--;         
                s.erase(s.begin() + i + 1);        
            } else break; 
        }
    }

    bool isValid(const string& s, int start, int end) {
        int num=0;
        if(start>end)return false;
        if(s[start]=='0'&&start!=end)return false;
        for(int i=start;i<=end;i++){
            if(s[i]<'0'||s[i]>'9')return false;
            num*=10;
            num+=s[i]-'0';
            if(num>255)return false;
        }
        return true;        
    }
public:
    vector<string> restoreIpAddresses(string s) {
        result.clear();
        if (s.size() < 4 || s.size() > 12) return result;
        backtracking(s,0);
        return result;
    }
};

78.子集


题目链接

思路

集合问题:操作和组合问题差不多,组合问题中path路径存入的每一步都是一个子集,所以用result保存path的每一步操作即可,该题目没有重复元素,所以不需要去重操作。

代码实现

   vector<vector<int>> result;
    vector<int> path;
    void backtracking(vector<int> &nums,int startIndex){
        if(startIndex==nums.size())return ;
        for(int i=startIndex;i<nums.size();i++){
            path.push_back(nums[i]);
            result.push_back(path);
            backtracking(nums,i+1);
            path.pop_back();
        }
        return;
        
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums,0);
        result.push_back(path);
        return result;
    }

90.子集II


题目链接

思路

集合问题:和组合问题的去重操作一样,但要记得先把集合内元素排序

代码实现

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    
    void backtracking(vector<int> &nums,int startIndex,vector<int> &used){
        if(startIndex==nums.size())return ;
        for(int i=startIndex;i<nums.size();i++){
            if(i>0&&nums[i]==nums[i-1]&&used[i-1]==0)continue;
            path.push_back(nums[i]);
            used[i]=1;
            result.push_back(path);
            backtracking(nums,i+1,used);
            used[i]=0;
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        vector<int> used(nums.size(),0);
        sort(nums.begin(),nums.end());
        backtracking(nums,0,used);
        result.push_back(path);
        return result;
    }
};

总结

分割问题

  1. 分割回文子串
    存整个字符串的一部分,依次向下切割
  2. 复原IP地址
    存整个字符串,在原有基础上切割
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值