day28 代码回想录 复原IP地址&子集&子集II

大纲

● 93.复原IP地址
● 78.子集
● 90.子集II

93.复原IP地址

题目:93.复原IP地址
复原ip地址,需要将字符串进行分隔,特别小心处理ip格式的判断
本题也是字符分割的题目,确定分割的点,作为递归参数传入

vector ret;
vector 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 getCombineIp(string& s) {
    _combineIp(s, 0);
    return ret;
}

78.子集

题目:78.子集
返回集合中元素可以组成的集合

// 求子集
// 思路从第一个元素开始遍历
// 结束条件:抵达最后一个元素
// 单层循环:[startIndex,i]区间取值并加入结果集合
// 错误在于最后一个元素会重复选,且没有[]包含

// 没有path保存回溯了 不知道是不是这个问题导致的错误
vector> ret1;
vector path1;
void _subArr(vector& nums, int startIndex)
{
    // 添加
    ret1.push_back(path1);
    if (startIndex >= nums.size()) {
        return;
    }
    for (int i = startIndex; i < nums.size(); ++i) {
//        vector 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> subArray(vector& nums) {
    _subArr(nums, 0);
    return ret1;
}

90.子集II

题目:90.子集II
本题和上一题的区别是集合中的元素会重复,需要处理重复的子集

// 求子集2
// 如果nums集合里面有重复元素
// 要求返回不重合的子集
// 排序,过滤掉相邻重复的元素
void _subArray2(vector & 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> subArray2(vector& nums) {
    sort(nums.begin(), nums.end());
    _subArray2(nums, 0);
    return ret1;
}

你可能感兴趣的:(数据结构,c++,算法,leetcode)