本文主要是介绍Leetcode 第 384 场周赛题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Leetcode 第 384 场周赛题解
- Leetcode 第 384 场周赛题解
- 题目1:3033. 修改矩阵
- 思路
- 代码
- 复杂度分析
- 题目2:3034. 匹配模式数组的子数组数目 I
- 思路
- 代码
- 复杂度分析
- 题目3:3035. 回文字符串的最大数量
- 思路
- 代码
- 复杂度分析
- 题目4:3036. 匹配模式数组的子数组数目 II
- 思路
- 代码
- 复杂度分析
Leetcode 第 384 场周赛题解
题目1:3033. 修改矩阵
思路
模拟。
代码
/** @lc app=leetcode.cn id=3033 lang=cpp** [3033] 修改矩阵*/// @lc code=start
class Solution
{
public:vector<vector<int>> modifiedMatrix(vector<vector<int>> &matrix){if (matrix.empty())return {};int m = matrix.size(), n = m ? matrix[0].size() : 0;auto answer = matrix;for (int i = 0; i < m; i++)for (int j = 0; j < n; j++){// 每个值为 -1 的元素需要替换if (matrix[i][j] == -1){// 找到列最大值int col_max = -1;for (int k = 0; k < m; k++)col_max = max(col_max, matrix[k][j]);// 修改 answer 数组answer[i][j] = col_max;}}return answer;}
};
// @lc code=end
复杂度分析
时间复杂度:O(m2*n),其中 m 和 n 分别是矩阵 matrix 的行数和列数。
空间复杂度:O(m*n),其中 m 和 n 分别是矩阵 matrix 的行数和列数。
题目2:3034. 匹配模式数组的子数组数目 I
思路
暴力。
设数组 nums 的长度为 m,数组 pattern 的长度为 n。
遍历数组 nums 的每个长度是 n+1 的子数组并计算子数组的模式,然后与数组 pattern 比较,如果相等则找到一个匹配模式数组的子数组。遍历结束之后即可得到匹配模式数组的子数组数目。
代码
/** @lc app=leetcode.cn id=3034 lang=cpp** [3034] 匹配模式数组的子数组数目 I*/// @lc code=start
class Solution
{
public:int countMatchingSubarrays(vector<int> &nums, vector<int> &pattern){// 特判if (nums.empty() || pattern.empty())return 0;if (nums.size() <= pattern.size())return 0;int count = 0;int m = nums.size(), n = pattern.size();for (int i = 0; i < m - n; i++){bool flag = true;for (int k = 0; k < n && flag; k++){int diff = nums[i + k + 1] - nums[i + k];int p = getPattern(diff);if (p != pattern[k])flag = false;}if (flag)count++;}return count;}// 辅函数 - 计算 patternint getPattern(int diff){if (diff == 0)return 0;return diff > 0 ? 1 : -1;}
};
// @lc code=end
复杂度分析
时间复杂度:O((m-n)*n),其中 m 为数组 nums 的长度,n 为数组 pattern 的长度。
空间复杂度:O(1)。
题目3:3035. 回文字符串的最大数量
思路
由于可以随意交换字母,先把所有字母都取出来,然后考虑如何填入各个字符串。
如果一个奇数长度字符串最终是回文串,那么它正中间的那个字母填什么都可以。
既然如此,不妨先把左右的字母填了,最后在往正中间填入字母。
字符串越短,需要的字母越少。
所以按照字符串的长度从小到大填。
统计所有字符串的长度之和,减去出现次数为奇数的字母,即为可以往左右填入的字母个数 total。
把字符串按照长度从小到大排序,然后遍历。注意长为奇数的字符串,由于不考虑正中间的字母,其长度要减一。
代码
/** @lc app=leetcode.cn id=3035 lang=cpp** [3035] 回文字符串的最大数量*/// @lc code=start
class Solution
{
public:int maxPalindromesAfterOperations(vector<string> &words){// 特判if (words.empty())return 0;int n = words.size();int total = 0; // 出现次数为偶数的字母总数unordered_map<char, int> mp;for (string &word : words){total += word.length();for (char &c : word)mp[c]++;}// 减去出现次数为奇数的字母for (auto &[ch, cnt] : mp)total -= cnt % 2;sort(words.begin(), words.end(), [](const string &s1, const string &s2){ return s1.length() < s2.length(); });int ans = 0;for (string &word : words){int len = word.length();// 长为奇数的字符串,长度要减一total -= len % 2 == 1 ? len - 1 : len;if (total < 0)break;ans++;}return ans;}
};
// @lc code=end
哈希表可以用位运算优化,详见:【灵茶山艾府】两种方法:正向思维 / 逆向思维(Python/Java/C++/Go)
复杂度分析
时间复杂度:O(L+nlogn),其中 n 是数组 words 的长度,L 是数组 words 中字符串的总长度。
空间复杂度:O(|∑|),其中 ∑ 是字符集,|∑| 为字符集的大小,因为 words[i] 仅由小写英文字母组成,所以 |∑|=26。
题目4:3036. 匹配模式数组的子数组数目 II
思路
设数组 nums 的长度为 m,数组 pattern 的长度为 n。
遍历数组 nums 的每个长度是 n+1 的子数组并计算子数组的模式,然后与数组 pattern 比较,如果相等则找到一个匹配模式数组的子数组。遍历结束之后即可得到匹配模式数组的子数组数目。
我们发现这其实就是 KMP。
将匹配模式转换成字符串:1 对应 ‘a’,0 对应 ‘b’,-1 对应 ‘c’。
代码
/** @lc app=leetcode.cn id=3036 lang=cpp** [3036] 匹配模式数组的子数组数目 II*/// @lc code=start// KMPclass Solution
{
private:// KMP 算法vector<int> getNxt(string &pattern){vector<int> nxt;// next[0] 必然是 0nxt.push_back(0);// 从 next[1] 开始求int x = 1, now = 0;while (x < pattern.length()){if (pattern[now] == pattern[x]){// 如果 pattern[now] == pattern[x],向右拓展一位now++;x++;nxt.push_back(now);}else if (now != 0){// 缩小 now,改成 nxt[now - 1]now = nxt[now - 1];}else{// now 已经为 0,无法再缩小,故 next[x] = 0nxt.push_back(0);x++;}}return nxt;}vector<int> kmp(string &s, string &pattern){int m = pattern.length();vector<int> nxt = getNxt(pattern);vector<int> res;int tar = 0; // 主串中将要匹配的位置int pos = 0; // 模式串中将要匹配的位置while (tar < s.length()){if (s[tar] == pattern[pos]){// 若两个字符相等,则 tar、pos 各进一步tar++;pos++;}else if (pos != 0){// 失配,如果 pos != 0,则依据 nxt 移动标尺pos = nxt[pos - 1];}else{// pos[0] 失配,标尺右移一位tar++;}if (pos == pattern.length()){res.push_back(tar - pos);pos = nxt[pos - 1];}}return res;}public:int countMatchingSubarrays(vector<int> &nums, vector<int> &pattern){// 特判if (nums.empty() || pattern.empty())return 0;if (nums.size() <= pattern.size())return 0;int count = 0;int m = nums.size(), n = pattern.size();// 1 对应 'a',0 对应 'b',-1 对应 'c'string s;for (int i = 0; i < m - 1; i++){int diff = nums[i + 1] - nums[i];int p = getPattern(diff);if (p == 1)s += "a";else if (p == 0)s += "b";elses += "c";}string p;for (int &pa : pattern){if (pa == 1)p += "a";else if (pa == 0)p += "b";elsep += "c";}return kmp(s, p).size();}// 辅函数 - 计算 patternint getPattern(int diff){if (diff == 0)return 0;return diff > 0 ? 1 : -1;}
};
// @lc code=end
复杂度分析
时间复杂度:O(m),其中 m 是数组 nums 的长度。
空间复杂度:O(n),其中 n 是数组 pattern 的长度。
这篇关于Leetcode 第 384 场周赛题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!