标签 Medium 下的文章

题目链接:分割回文串

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

方法一:DFS+逗号分割

class Solution {
public:
    vector<vector<string>> ans;
    vector<string> path;
    bool is_hw(string s,int start,int end) {
        while (start < end) {
            if (s[start++] != s[end--]) return false;
        }
        return true;
    }
    void dfs(string s,int start,int i) {
        if (i == s.size()) {
            ans.push_back(path);
            return ;
        }
        if (i < s.size() - 1) {
            dfs(s,start,i+1);
        }
        if (is_hw(s,start,i)) {
            path.push_back(s.substr(start,i-start+1));
            dfs(s,i+1,i+1);
            path.pop_back();
        }
    }
    vector<vector<string>> partition(string s) {
        dfs(s,0,0);
        return ans;
    }
};

方法二:DFS+遍历

class Solution {
public:
    vector<vector<string>> ans;
    vector<string> path;
    bool is_hw(string s,int start,int end) {
        while (start < end) {
            if (s[start++] != s[end--]) return false;
        }
        return true;
    }
    void dfs(string s,int i) {
        if (i == s.size()) {
            ans.push_back(path);
            return ;
        }
        for (int j = i;j < s.size();j++) {
            if (!is_hw(s,i,j)) continue;
            path.push_back(s.substr(i,j-i+1));
            dfs(s,j+1);
            path.pop_back();
        }
    }
    vector<vector<string>> partition(string s) {
        dfs(s,0);
        return ans;
    }
};

方法三:DP+DFS

class Solution {
public:
    vector<vector<string>> ans;
    vector<string> path;
    vector<vector<bool>> isPal;
    void buildPal(string s) {
        isPal.assign(s.size(),vector<bool>(s.size(),false));
        for (int i = s.size() - 1;i >= 0;i--) {
            for (int j = i;j < s.size();j++) {
                if (s[i] == s[j] && (j-i <= 2 || isPal[i+1][j-1])) {
                    isPal[i][j] = true;
                }
            }
        }
    }
    void dfs(string s,int i) {
        if (i == s.size()) {
            ans.push_back(path);
            return ;
        }
        for (int j = i;j < s.size();j++) {
            if (!isPal[i][j]) continue;
            path.push_back(s.substr(i,j-i+1));
            dfs(s,j+1);
            path.pop_back();
        }
    }
    vector<vector<string>> partition(string s) {
        buildPal(s);
        dfs(s,0);
        return ans;
    }
};

题目链接:括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

方法一:递归

class Solution {
public:
    vector<string> generateParenthesis(int n) {
        dfs("",n,n);
        return res;
    }
    vector<string> res;
    void dfs(const string& str,int left,int right) {
        if (left < 0 || left > right) return ;
        if (left == 0 && right == 0) {
            res.push_back(str);
            return ;
        }
        dfs(str + '(',left - 1,right);
        dfs(str + ')',left,right - 1);
    }
};

题目链接:前 K 个高频元素

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

方法一:桶排序

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> cnt;
        int max_cnt = 0;
        for (int x : nums) {
            cnt[x]++;
            max_cnt = max(max_cnt,cnt[x]);
        }
        vector<vector<int>> buckets(max_cnt+1);
        for (auto& [x,c] : cnt) {
            buckets[c].push_back(x);
        }
        vector<int> ans;
        for (int i = max_cnt;i >= 0 && ans.size() < k;i--) {
            ans.insert(ans.end(),buckets[i].begin(),buckets[i].end());
        }
        return ans;
    }
};

题目链接:数组中的第K个最大元素

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

方法一:快速选择

class Solution {
public:
    int quickSelect(vector<int>& nums,int k) {
        int pivot = nums[rand() % nums.size()];
        vector<int> big,equal,small;
        for (int num : nums) {
            if (num > pivot) {
                big.push_back(num);
            }else if (num < pivot) {
                small.push_back(num);
            }else {
                equal.push_back(num);
            }
        }
        if (k <= big.size()) {
            return quickSelect(big,k);
        }
        if (nums.size() - small.size() < k) {
            return quickSelect(small,k - nums.size() + small.size());
        }
        return pivot;
    }
    int findKthLargest(vector<int>& nums, int k) {
        return quickSelect(nums,k);
    }
};

题目链接:字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

测试用例保证输出的长度不会超过 105。

方法一:栈

class Solution {
public:
    string decodeString(string s) {
        string res = "";
        stack<int> nums;
        stack<string> strs;
        int num = 0;
        int len = s.size();
        for (int i = 0;i < len;i++) {
            if (s[i] >= '0' && s[i] <= '9') {
                num = num * 10 + s[i] - '0';
            }else if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
                res = res + s[i];
            }else if (s[i] == '[') {
                nums.push(num);
                num = 0;
                strs.push(res);
                res = "";
            }else {
                int times = nums.top();
                nums.pop();
                for (int j = 0;j < times;j++) {
                    strs.top() += res;
                }
                res = strs.top();
                strs.pop();
            }
        }
        return res;
    }
};