class Solution {
private:
vector<string> result;
void bt(string s, string path, int lay){
if(s.size()<lay||s.size()>3*lay) return;
int sum=0;
if(lay==1){
if(s[0]=='0'){
if(s.size()==1){
result.push_back(path+"0");
}else{
return;
}
}else{
for(int i=0;i<s.size();i++){
sum=sum*10+(s[i]-'0');
}
if(sum<256){
result.push_back(path+to_string(sum));
}
return;
}
}else{
if(s[0]=='0'){
bt(s.substr(1,s.size()),path+"0"+".",lay-1);
}else{
for(int i=0;i<3&&i<s.size();i++){
sum=sum*10+(s[i]-'0');
if(sum>255) return;
bt(s.substr(i+1,s.size()),path+to_string(sum)+".",lay-1);
}
}
}
}
public:
vector<string> restoreIpAddresses(string s) {
for(int i=0;i<s.size();i++){
if(s[i]<'0'||s[i]>'9') return result;
}
string path="";
bt(s,path,4);
return result;
}
};
在这题中,主要注意的就是对0的处理,当拿到的字符串第一位是'0'时,就不需要再看0以后是什么,而是将0加入path字符串,判断是否继续穷举。由于要将字符串风味4部分,而'.'只有3个,所以笔者选择在回溯函数中加入一个layer参数,当到最后一块IP地址时,layer==1,此时不再逐位穷举,而是判断第一位是否为0,或直接将剩余字符串转为数字,判断是否符合IP地址要求。layer不为1时,则在将数字字符串加入path后再加"."。
class Solution {
private:
vector<vector<int>>result;
vector<int>path;
void bt(vector<int>& nums, int l, int lay){
if(lay==-1){
result.push_back(path);
return;
}
for(int i=l;i<nums.size()-lay;i++){
path.push_back(nums[i]);
bt(nums,i+1,lay-1);
path.pop_back();
}
}
public:
vector<vector<int>> subsets(vector<int>& nums) {
for(int i=0;i<=nums.size();i++){
bt(nums,0,i-1);
}
return result;
}
};
这题与此前做到的求取组合的区别在于这题组合的长度可变,所以只要在求取固定长度组合的基础上,对nums可能存在的组合长度进行穷举即可。
class Solution {
private:
vector<vector<int>>result;
vector<int>path;
void bt(vector<int>& nums, int l, int lay){
if(lay==-1){
result.push_back(path);
return;
}
for(int i=l;i<nums.size()-lay;i++){
path.push_back(nums[i]);
bt(nums,i+1,lay-1);
while(i<nums.size()-lay-1){
if(nums[i]!=nums[i+1]) break;
i++;
}
path.pop_back();
}
}
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
for(int i=0;i<=nums.size();i++){
bt(nums,0,i-1);
}
return result;
}
};
这题与上题的区别在于,nums中的数字可能存在重复,且乱序,要保证求取的组合没有重复。要实现降重,只需对nums先进行排序,在每次回溯后,跳过与当前数字相同的数字即可。