LeetCode Day30

55 阅读3分钟

131. 分割回文串(昨天的题放在今天一起做)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。

示例 1: 输入:s = "aab" 输出:[["a","a","b"],["aa","b"]] 示例 2: 输入:s = "a" 输出:[["a"]]

提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

思路

  1. 定义数据结构 result:存储所有满足条件的组合。 current:存储当前正在构建的组合。
  2. 辅助函数:检查回文 定义一个函数来检查一个字符串是否是回文。
  3. 回溯函数 该函数主要执行以下操作:

结束条件:如果字符串 s 为空,说明已找到一个有效的组合,将其添加到 result。 选择与回溯:从字符串 s 中选择一个回文子串,并加入到 current。然后递归调用回溯函数。最后,撤销这一选择。

  1. 主函数 partition 在主函数中,调用回溯函数,并最终返回 result。

题解

class Solution {
private:
    vector<vector<string>> result;
    vector<string> current;

    // 辅助函数:检查回文
    bool isPalindrome(const string& s) {
        int left = 0, right = s.size() - 1;
        while (left < right) {
            if (s[left] != s[right]) return false;
            left++;
            right--;
        }
        return true;
    }

public:
    void backtracking(string& s, int start) {
        // 结束条件
        if (start == s.size()) {
            result.push_back(current);
            return;
        }
        for (int end = start; end < s.size(); ++end) {
            // 选择一个子串 [start, end]
            string sub = s.substr(start, end - start + 1);
            // 检查是否为回文
            if (isPalindrome(sub)) {
                current.push_back(sub);  // 选择
                backtracking(s, end + 1);  // 回溯
                current.pop_back();  // 撤销选择
            }
        }
    }

    vector<vector<string>> partition(string s) {
        backtracking(s, 0);
        return result;
    }
};

93. 复原 IP 地址

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。

  • 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
  • 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。 示例 1: 输入:s = "25525511135" 输出:["255.255.11.135","255.255.111.35"] 示例 2: 输入:s = "0000" 输出:["0.0.0.0"] 示例 3: 输入:s = "101023" 输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"] 提示:
  • 1 <= s.length <= 20
  • s 仅由数字组成

思路

从字符串的第一个字符开始,逐步尝试选择 1-3 个数字作为 IP 地址的一个部分,然后进入下一层递归。在递归过程中,需要注意以下几点:

  1. 每个 IP 地址部分应是一个 0-255 之间的整数。
  2. 如果一个 IP 地址部分以 '0' 开头,那么它只能是 '0'。
  3. 最终的 IP 地址必须有 4 部分。
  4. 其他部分参考上题

题解

class Solution {
private:
    vector<string> result;
    vector<string> current;

    // 辅助函数:检查子串是否有效
    bool isValid(const string& s) {
        if (s.empty() || s.size() > 3 || (s.size() > 1 && s[0] == '0') || stoi(s) > 255) {
            return false;
        }
        return true;
    }

public:
    void backtracking(string& s, int start) {
        // 结束条件:找到 4 个有效部分且使用了所有字符
        if (current.size() == 4 && start == s.size()) {
            result.push_back(current[0] + '.' + current[1] + '.' + current[2] + '.' + current[3]);
            return;
        }
        // 结束条件:找到 4 个部分但未使用所有字符,或使用了所有字符但未找到 4 个部分
        if (current.size() == 4 || start == s.size()) {
            return;
        }
        for (int end = start; end < s.size(); ++end) {
            // 选择一个子串 [start, end]
            string sub = s.substr(start, end - start + 1);
            // 检查是否有效
            if (isValid(sub)) {
                current.push_back(sub);  // 选择
                backtracking(s, end + 1);  // 回溯
                current.pop_back();  // 撤销选择
            }
        }
    }

    vector<string> restoreIpAddresses(string s) {
        backtracking(s, 0);
        return result;
    }
};