代码训练营Day.28 | 93. 复原IP地址、78. 子集、90. 子集II

93. 复原IP地址

1. LeetCode链接

. - 力扣(LeetCode)

2. 题目描述

代码训练营Day.28 | 93. 复原IP地址、78. 子集、90. 子集II_第1张图片

代码训练营Day.28 | 93. 复原IP地址、78. 子集、90. 子集II_第2张图片

3. 解法

字符串切四刀,最后一刀必须是在末位。

麻烦的地方在于文本的各种限制条件、剪枝等等。

class Solution {
public:
    vector results;
    string result;
    void backtracking(string& s, int start, int k) {
        if (start == s.size() && k == -1) {
            result.pop_back();
            results.push_back(result);
            result.push_back('.');
            return;
        }
        string ss;
        for (int i = start; i < s.size(); i++) {
            if (k == 0) { // 要是前三刀切完了,第四刀必须在末尾
                ss = s.substr(start, s.size() - start);
                i = s.size() - 1;
            }
            else ss = s.substr(start, i + 1 - start);
            if (ss[0] == '0' && ss.size() > 1) break; // 开头‘0’不合法,后面的也不用考虑
            if (ss.size() > 3) break; // size大于3,肯定>255,后面也不用考虑
            int num = stoi(ss);
            if (num > 255) break; // >255,后面也不用考虑了。
            result += ss;
            result.push_back('.');
            backtracking(s, i + 1, k - 1);
            result.erase(result.end() - ss.size() - 1, result.end());
        }
        return;
    }
    vector restoreIpAddresses(string s) {
        backtracking(s, 0, 3);
        return results;
    }
};

该方法不太省空间。以下方法直接在s上操作,考虑将三个‘.’插在字符串的哪里。注意第三个点插在最后一位的情况。

class Solution {
public:
    vector result;
    void backtracking(string& s, int pp, int start) {
        if (pp == 3) {
            if (isValid(s, start, s.size() - 1)) result.push_back(s);
            return;
        }
        for (int i = start; i < s.size(); i++) {
            if (isValid(s, start, i)) {
                s.insert(s.begin() + i + 1, '.');
                pp++;
                backtracking(s, pp, i + 2);
                pp--;
                s.erase(s.begin() + i + 1);
            } else break;
        }
    }
    bool isValid(string& s, int left, int right) {
        if (left > right) return false;  // 防止最后一位是‘.’
        if (s[left] == '0' && right > left) return false;
        if ((right - left) > 3) return false;
        int num = 0;
        for (int i = left; i <= right; i++) {
            if (s[i] > '9' || s[i] < '0') return false;
            num = num * 10 + (s[i] - '0');
            if (num > 255) return false;
        }
        return true;
    }
    vector restoreIpAddresses(string s) {
        backtracking(s, 0, 0);
        return result;
    }
};

78. 子集

1. LeetCode链接

. - 力扣(LeetCode)

2. 题目描述

代码训练营Day.28 | 93. 复原IP地址、78. 子集、90. 子集II_第3张图片

代码训练营Day.28 | 93. 复原IP地址、78. 子集、90. 子集II_第4张图片

3. 解法

太简单了,就是组合但是不考虑长度,任何都能压入最终答案中。

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

90. 子集II

1. LeetCode链接

90. 子集 II - 力扣(LeetCode)

2. 题目描述

代码训练营Day.28 | 93. 复原IP地址、78. 子集、90. 子集II_第5张图片

3. 解法

有了重复元素,就不得不先排序了。

class Solution {
public:
    vector> results;
    vector result;
    void backtracking(vector& nums, int start) {
        results.push_back(result);
        for (int i = start; i < nums.size(); i++) {
            if (i > start && nums[i] == nums[i - 1]) continue;
            result.push_back(nums[i]);
            backtracking(nums, i + 1);
            result.pop_back();
        }
        return;
    }
    vector> subsetsWithDup(vector& nums) {
        sort(nums.begin(), nums.end());
        backtracking(nums, 0);
        return results;
    }
};

你可能感兴趣的:(leetcode,算法,职场和发展)