代码随想录算法训练营第30天-93.复原IP地址-78.子集-90.子集II

93.复原IP地址

1.正常回溯就可以

我的做法是,先用vector存放ip,然后用函数vec2str()转化为字符串。

其他的就是正常的回溯,有一些值得说的小细节:

  • 因为最多就3位,所以切分时补充一个上限3位
  • 出现01这种前导0不允许,要在判别时剔除
  • 整数转字符串用to_string(),字符串转整数用stoi()
vector<string> res;
vector<int> ip;

string vec2str(vector<int>& vec)
{
    string tmp;
    for (auto& x : vec)
    {
        tmp.append(to_string(x));
        tmp.append(".");
    }
    tmp.pop_back();
    return tmp;
}

void backtracing(const string& s, int startIndex)
{  
    //段数多于4,不合法
    if (ip.size() > 4) return;

    //切割到底,段数等于4,合法
    if (startIndex >= s.size() && ip.size() == 4)
    {
        res.push_back(vec2str(ip));
        return;
    }

    for (int i = startIndex; i < s.size() && i < startIndex + 3; i++)
    {
        string tmp = s.substr(startIndex, i - startIndex + 1);
        //合法性判别,位于0~255,没有前导0(除非只有0)
        if (stoi(tmp) > -1 && stoi(tmp) < 256 && !(tmp.size() > 1 && tmp[0] == '0'))
        {
            ip.push_back(stoi(tmp));
            backtracing(s, i + 1);
            ip.pop_back();
        }
        else 
        {
            continue;
        }
    }
}

vector<string> restoreIpAddresses(string s) {
    res.clear();
    ip.clear();

    if (s.empty()) return res;

    backtracing(s, 0);
    return res;
}

2.代码随想录的方法

我简单看了下,用单独的数字记录段数,单独的函数判别合法性。

回溯也不是死套路,能跑就行啦~

78.子集

终于到了回溯的第三种常见问题——子集

集合问题与组合和切割不同的地方就是,它需要整棵树上所有的结点,这个我在切割回文的那道题也尝试过这么做,思路就是叶结点只负责返回,而每个回溯开始时都将此时结果添加到结果

其实终止条件可以不写,因为当startIndex超过nums.size()时,就不会再进入循环了

vector<vector<int>> res;
vector<int> path;

void backtracing(vector<int>& nums, int startIndex)
{
    res.push_back(path);

    if (startIndex >= nums.size()) return;

    for (int i = startIndex; i < nums.size(); i++)
    {
        path.push_back(nums[i]);
        backtracing(nums, i + 1);
        path.pop_back();
    }
}

vector<vector<int>> subsets(vector<int>& nums) {
    res.clear();
    path.clear();

    backtracing(nums, 0);
    return res;
}

90.子集II

这个题目又涉及到重复的问题,跟组合的重复其实很像,当出现了1,1,2这种情况时,结果会出现两个1,2,我们认为是不合法的。

这个解决方案也一样,在可选择范围内,同则跳过(nums得先排序)

vector<vector<int>> res;
vector<int> path;

void backtracing(vector<int>& nums, int startIndex)
{
    res.push_back(path);

    if (startIndex >= nums.size()) return;

    for (int i = startIndex; i < nums.size(); i++)
    {
        if (i > startIndex && nums[i] == nums[i - 1]) continue;

        path.push_back(nums[i]);
        backtracing(nums, i + 1);
        path.pop_back();
    }
}

vector<vector<int>> subsetsWithDup(vector<int>& nums) {
    res.clear();
    path.clear();

    sort(nums.begin(), nums.end());

    backtracing(nums, 0);
    return res;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

去人777

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值