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

2025-08-01

93.复原IP地址

题目链接:93.复原IP地址
文档讲解:代码随想录
状态:很多细节调试后AC

思路

本题也是分割问题,与分割回文串相仿,但是细节要求更多!下面说一下容易踩的坑:

  1. 收集条件判断: 以为和回文串一样,s为空(或者start下标到末尾)就结束了,实则有逗号数量的要求,这里着重了解s为空的判断方法,使用empty而不是迭代器;对于逗号的计数使用count,语法为:count(ip.begin(),ip.end(),'.')
  2. 收集中的回溯: 在收集时需要去掉末尾的最后一个逗号,但是记得返回时要加回来!因为当前的答案仅仅是一个小树的终止,还要返回父节点继续寻找答案,必须要正确返回。
  3. for循环边界: 在树层遍历时只考虑3个没毛病,但是要基于不越界的前提下。

题解

class Solution {
public:
    vector<string> res;
    string ip;
    bool isip(string s)
    {
        if(s.size()!=1 && s[0] == '0')return false;
        else
        {
            int num = stoi(s);
            if(num>=0 && num<=255)return true;
            else return false;
        }
    }
    void backtracking(string s)
    {
        if(count(ip.begin(),ip.end(),'.')>4)return;
        if(s.empty() && count(ip.begin(),ip.end(),'.') == 4)
        {
            ip.pop_back();
            res.push_back(ip);
            ip += ".";
            return;
        }
        for(int i = 1;i<=3 && i<=s.size();i++)
        {
            string temp1(s.begin(),s.begin()+i);
            if(isip(temp1))
            {
                ip = ip+temp1+".";
                string temp2(s.begin()+i,s.end());
                backtracking(temp2);
                for(int j = 0;j<=temp1.size();j++)ip.pop_back();
            }
        }
    }
    vector<string> restoreIpAddresses(string s) {
        backtracking(s);
        return res;
    }
};

78.子集

题目链接:78.子集
文档讲解:代码随想录
状态:轻松AC

思路

子集问题比组合问题还TM的简单!

因为子集问题递归到的情况都要收集,没有判断条件。

渗透子集思想,以及与组合的不同

题解

class Solution {
public:
    vector<int> path;
    vector<vector<int>> res;
    void backtracking(vector<int>& nums,int start)
    {
        res.push_back(path);
        for(int i = start;i<nums.size();i++)
        {
            path.push_back(nums[i]);
            backtracking(nums,i+1);
            path.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        backtracking(nums,0);
        return res;
    }
};

90.子集II

题目链接:90.子集II
文档讲解:代码随想录
状态:轻松AC,

思路

与之前组合的去重逻辑一模一样,不多解释。

但是,做该题时对于while该放置的地方疑惑,在宏观上总体思考,要这个子树全部完成后,后面重复跳过,就知道了要放在回溯函数的后面。

题解

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

马上补完进度了——康宁湖游记