day28 2023/02/28
一、复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
分析如下:
本题依旧可以抽象成树形结构
切割问题可以抽象为树型结构,如图:
代码如下:
注明:复习C++中insert函数以及erase函数的用法/本题与计算机网络结合
class Solution {
public:
vector<string> result;
string s;
bool isValidNet(string& str,int start,int end)
{
if(start>end) return false;
if(str[start]=='0'&&start!=end)//0开头的不合法
{
return false;
}
int num=0;
for(int i=start;i<=end;i++)
{
//遇到非数字字符直接返回错误
if(str[i]<'0'||str[i]>'9')
return false;
//大于255也返回错误
num=num*10+(str[i]-'0');
if(num>255)
return false;
}
return true;
}
void backtracking(string& s,int startIndex,int pointNum)//pointNum代表句点个数
{
if(pointNum==3)
{
if(isValidNet(s,startIndex,s.size()-1)==true)
{
result.push_back(s);
return;
}
}
for(int i=startIndex;i<s.size();i++)
{
if(isValidNet(s,startIndex,i)==true)
{
s.insert(s.begin()+i+1,'.');
pointNum++;
backtracking(s,i+2,pointNum);//注意这里是从i+2开始呢
s.erase(s.begin()+i+1);
pointNum--;
}
else break;
}
}
vector<string> restoreIpAddresses(string s) {
backtracking(s,0,0);
return result;
}
};
二、子集
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
分析如下:
以示例中nums = [1,2,3]为例把求子集抽象为树型结构,如下:
代码如下:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int> & nums,int startIndex)
{
result.push_back(path);
if(startIndex>=nums.size())
{
return ;
}
for(int i=startIndex;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 result;
}
};
三、子集Ⅱ
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
分析如下:
理解“树层去重”和“树枝去重”非常重要。
用示例中的[1, 2, 2] 来举例,如图所示: (注意去重需要先对集合排序)
代码如下:
注意:去重需要排序
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backtracking(vector<int>& nums,int startIndex,vector<bool>& used)
{
result.push_back(path);
if(startIndex>=nums.size())
return;
for(int i=startIndex;i<nums.size();i++)
{
if(i>0&&nums[i]==nums[i-1]&&used[i-1]==false)//去重操作想清楚
continue;
used[i]=true;
path.push_back(nums[i]);
backtracking(nums,i+1,used);
used[i]=false;
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<bool> used(nums.size(),false);
sort(nums.begin(),nums.end());//排序别忘了
backtracking(nums,0,used);
return result;
}
};
四、差分(自学内容)
一维差分:
给区间[l,r]中的每个数加上c:b[l]+=c , b[r-1]-=c
二维差分:
给以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵中的所有元素加上c
s[x1,y1]+=c,s[x2+1,y1]-=c,s[x1,y2+1]-=c,s[x2+1,y2+1]+=c