代码随想录训练营第28天|93.复原IP地址、78.子集、90.子集Ⅱ

17 篇文章 0 订阅

93.复原IP地址78.子集90.子集Ⅱ

93.复原IP 地址

这道题与昨天的回文子串很像,

我们可以创建一个函数bool isip(string& ss,int start,int end)
来判断此次分割的字符串是否是介于【0,255】。输入的参数包括
string ss, 题目所给的字符串ss,
int start,需要判断的字符串的起始位置,
int end,需要判断的字符串的末尾位置。
对于该函数,如果起始位置是零,并且end!=start,表示需要判断的字符串不只一位,且首位是零。因此我们直接返回false就行。不然,我们就将这个字符串转化为int类型,再判断。定义一个int类型num=0;对于字符串的每一位,我们都先让num*10,再加上这个字符代表的数字。

bool isip(string& ss,int start,int end)
{
    if(ss[start]=='0'&&start!=end||start>end) return false;
    int num=0;
    for(int ii = start;ii<=end;ii++)
    {
        num*=10;
        num+=(ss[ii]-'0');
    }
    if(num>255) return false;
    return true;
}

对于给定的字符串ss,如果它的大小小于4,或者大于12,我们直接返回空字符串数组(分成四份的话,至少保证每份至少有一位数至多三位数)。

最重要的是回溯递归。

我们需要提前确定参数,首先是字符串本身,然后是每次循环的起始位置,最后是插入的点的个数。
所以回溯函数定为void backtracking(string& ss,int start,int point)
如果point==3,我们先判断最后的字符串是不是合法的,如果合法,我们直接将结果加入到result;
不然,我们从起始位置进行循环,最多循环三位数(保证循环的ii不超过字符串大小),让子符串在ii+1的位置插入一个‘.’,并且让point++;然后进行回溯,回溯结束后,把这个‘.’删除,point–即可。

代码

class Solution {
public:
vector<string> result;
bool isip(string& ss,int start,int end)
{
    if(ss[start]=='0'&&start!=end||start>end) return false;
    int num=0;
    for(int ii = start;ii<=end;ii++)
    {
        num*=10;
        num+=(ss[ii]-'0');
    }
    if(num>255) return false;
    return true;
}
void backtracking(string& ss,int start,int point)
{
    if(point ==3)
    {
        if(isip(ss,start,ss.size()-1))
        result.push_back(ss);
    }
    else{
        for(int ii = start;ii<start+3&&ii<ss.size();ii++)
        {
            if(!isip(ss,start,ii))
            break;
            else
            {
                ss.insert(ss.begin()+ii+1,'.');
                point++;
                backtracking(ss,ii+2,point);
                point--;
                ss.erase(ss.begin()+ii+1);
            }
            
        }

    }
}
    vector<string> restoreIpAddresses(string s) {
        if(s.size()<4||s.size()>12)
        return result;
        backtracking(s,0,0);
        return result;
    }
};

78.子集

对于子集,我们定义全局变量
二维变量vector<vector<int>> result;用于存储结果。
一维变量vector<int> temp;用于存储当前的数组元素。
如果给定的数组为空,我们就给result加入一个空数组,当作子集,直接输出。
如果不为空,就进行递归回溯。
我们递归回溯过程,我们直接将temp加入到result中(空集,全集也是子集),并从起始位置进行循环,将result【ii】加入到temp,并从下一位置进行递归,递归结束就把加入的元素弹出来。

代码

class Solution {
public:
vector<vector<int>> result;
vector<int> temp;
void backtracking(vector<int>&nums,int start)
{
    result.push_back(temp);
    for(int ii = start;ii<nums.size();ii++)
    {
        temp.push_back(nums[ii]);
        backtracking(nums,ii+1);
        temp.pop_back();
    }
}
    vector<vector<int>> subsets(vector<int>& nums) {

        if(nums.empty()) 
        {
            result.push_back(temp);
            return result;
        }
        backtracking(nums,0);
        return result;
    }
};

90.子集Ⅱ

该问题是子集问题和组合总和问题的组合形式,既要求子集,所给数组还有重复元素,还要避免答案中组合重复。
因此,我们先判断该数组,如果为空,返回一个含空集的数组。
如果不为空,就进行递归回溯,
递归回溯中,我们先将temp放入到result之中,进行for循环递归,同组合问题一样,为了避免重复访问相同数字,如果不是start,我们就避免其与前一个元素相同,用while循环对循环下标进行++。

class Solution {
public:
vector<vector<int>>result;
vector<int>temp;
void backtracking(vector<int>nums,int start)
{
        result.push_back(temp);
    for(int ii =start;ii<nums.size();ii++)
    {
        if(ii>start)
        {
            while(ii<nums.size()&&nums[ii]==nums[ii-1])
            ii++;
        }
        if(ii<nums.size())
        {
            temp.push_back(nums[ii]);
            backtracking(nums,ii+1);
            temp.pop_back();
        }
    }
}
    vector<vector<int>> subsetsWithDup(vector<int>& nums) {
        if(nums.size()==0)
        {
            result.push_back(temp);
            return result;
        }
        sort(nums.begin(),nums.end());
        backtracking(nums,0);
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值