大纲
● 93.复原IP地址
● 78.子集
● 90.子集II
93.复原IP地址
题目:93.复原IP地址
复原ip地址,需要将字符串进行分隔,特别小心处理ip格式的判断
本题也是字符分割的题目,确定分割的点,作为递归参数传入
vector<string> ret;
vector<string> path;
// 没有考虑到不是ip,如果不是ip格式 当path > 4 或者小于3, 判断ip逻辑错误,需要加上0开头删除
// substr()参数传错误了
bool isIp(string& s, int startIndex, int endIndex)
{
int sum = 0;
for (int i = startIndex; i < endIndex + 1; ++i) {
sum += (s[i] - '0') * 10 ^ (endIndex - i);
}
// count << "sum:" << sum << endl;
if (sum >= 0 && sum <= 255)
return true;
return false;
}
bool isIp2(string& s, int startIndex, int endIndex) {
string tmp = s.substr(startIndex, endIndex - startIndex + 1);
// 删除0开头的
if (tmp.size() > 1 && tmp[0] == '0')
return false;
int val = std::atoi(tmp.c_str());
if (val >= 0 && val <= 255)
return true;
return false;
}
void _combineIp(string& s, int splitIndex)
{
// 如果不是ip格式 当path > 4 或者path < 4也不是
if (path.size() > 4) {
return;
}
// 当所有字符都切割完了
if (splitIndex >= s.size() && path.size() == 4) {
// 组成ip地址
string s;
for (int i = 0; i < path.size(); ++i) {
s.append(path[i]);
if (i != path.size() - 1)
s.append(".");
}
ret.push_back(s);
return;
}
// 切割剩下的字符 [splitIndex, i]
for (int i = splitIndex; i < s.size(); ++i) {
if (!isIp(s, splitIndex, i)) {
continue;
}
string sub = s.substr(splitIndex, s.size() - i + 1);
path.push_back(sub);
_combineIp(s, i + 1);
path.pop_back();
}
}
vector<string> getCombineIp(string& s) {
_combineIp(s, 0);
return ret;
}
78.子集
题目:78.子集
返回集合中元素可以组成的集合
// 求子集
// 思路从第一个元素开始遍历
// 结束条件:抵达最后一个元素
// 单层循环:[startIndex,i]区间取值并加入结果集合
// 错误在于最后一个元素会重复选,且没有[]包含
// 没有path保存回溯了 不知道是不是这个问题导致的错误
vector<vector<int>> ret1;
vector<int> path1;
void _subArr(vector<int>& nums, int startIndex)
{
// 添加
ret1.push_back(path1);
if (startIndex >= nums.size()) {
return;
}
for (int i = startIndex; i < nums.size(); ++i) {
// vector<int> tmp(nums.begin() + startIndex, nums.begin() + i + 1);
// ret1.push_back(tmp);
path1.push_back(nums[i]);
_subArr(nums, i + 1);
path1.pop_back();
}
}
vector<vector<int>> subArray(vector<int>& nums) {
_subArr(nums, 0);
return ret1;
}
90.子集II
题目:90.子集II
本题和上一题的区别是集合中的元素会重复,需要处理重复的子集
// 求子集2
// 如果nums集合里面有重复元素
// 要求返回不重合的子集
// 排序,过滤掉相邻重复的元素
void _subArray2(vector<int> & nums, int sliderIndex) {
ret1.push_back(path1);
if (sliderIndex >= nums.size()) return;
for (int i = sliderIndex; i < nums.size(); ++i) {
// 过滤重复元素
if (i > sliderIndex && nums[i - 1] == nums[i])
continue;
path1.push_back(nums[i]);
_subArray2(nums, i + 1);
path1.pop_back();
}
}
vector<vector<int>> subArray2(vector<int>& nums) {
sort(nums.begin(), nums.end());
_subArray2(nums, 0);
return ret1;
}