Leetcode 第 383 场周赛题解
Leetcode 第 383 场周赛题解
题目1:3028. 边界上的蚂蚁
思路
遍历下标 i,1<=i<=nums.length(),返回 accumulate(nums.begin(), nums.begin() + i, 0) = 0 的次数。
代码
class Solution
{
public:
int returnToBoundaryCount(vector<int> &nums)
{
int count = 0;
int sum = 0;
for (int &num : nums)
{
sum += num;
if (!sum)
count++;
}
return count;
}
};
复杂度分析
时间复杂度:O(n)。
空间复杂度:O(1)。
题目2:3029. 将单词恢复初始状态所需的最短时间 I
思路
暴力。
不断删除前 k 个字符,一旦发现此时删除后的字符串和原字符串的前缀相等,那么就不需要再删除了,因为后续的添加的字符是可以任意指定的。
举个例子,对于示例 1,abacaba,k=3:
- 第一次删除:变成 caba###,#表示可以添加的任意字符,此时删除后的字符串是 caba,没有与原字符串中任意字符串匹配;
- 第二次删除:变成 a######,此时删除后的字符串是 a,与原字符串的前缀 a 匹配成功,那么后续就不用再删了,因为后面的 # 是可以改为任意字符的,所以可以恢复到初始状态。
代码
/*
* @lc app=leetcode.cn id=3029 lang=cpp
*
* [3029] 将单词恢复初始状态所需的最短时间 I
*/
// @lc code=start
// 暴力
class Solution
{
public:
int minimumTimeToInitialState(string word, int k)
{
int n = word.size();
int time = 0;
for (int i = 0; i < n; i += k)
{
time++;
if (i + k < n)
{
string temp = word.substr(i + k);
if (word.substr(0, temp.size()) == temp)
break;
}
}
return time;
}
};
// @lc code=end
复杂度分析
时间复杂度:O(n),n 是字符串 s 的长度。
空间复杂度:O(1)。
题目3:3030. 找出网格的区域平均强度
思路
模拟。
代码
/*
* @lc app=leetcode.cn id=3030 lang=cpp
*
* [3030] 找出网格的区域平均强度
*/
// @lc code=start
// 模拟
class Solution
{
public:
vector<vector<int>> resultGrid(vector<vector<int>> &image, int threshold)
{
int m = image.size(), n = m ? image[0].size() : 0;
vector<vector<int>> result(m, vector<int>(n));
vector<vector<int>> cnt(m, vector<int>(n));
for (int i = 2; i < m; i++)
{
for (int j = 2; j < n; j++)
{
// 检查左右相邻格子
bool ok = true;
for (int x = i - 2; x <= i; x++)
{
if (abs(image[x][j - 2] - image[x][j - 1]) > threshold ||
abs(image[x][j - 1] - image[x][j]) > threshold)
{
ok = false;
break; // 不合法,下一个
}
}
if (!ok)
continue;
// 检查上下相邻格子
for (int y = j - 2; y <= j; y++)
{
if (abs(image[i - 2][y] - image[i - 1][y]) > threshold ||
abs(image[i - 1][y] - image[i][y]) > threshold)
{
ok = false;
break; // 不合法,下一个
}
}
if (!ok)
continue;
// 合法,计算 3x3 子网格的平均值
int avg = 0;
for (int x = i - 2; x <= i; x++)
for (int y = j - 2; y <= j; y++)
avg += image[x][y];
avg /= 9;
// 更新 3x3 子网格内的 result
for (int x = i - 2; x <= i; x++)
for (int y = j - 2; y <= j; y++)
{
result[x][y] += avg; // 先累加,最后再求平均值
cnt[x][y]++;
}
}
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
{
if (cnt[i][j] == 0)
{
// (i,j) 不属于任何子网格
result[i][j] = image[i][j];
}
else
{
// 求平均值
result[i][j] /= cnt[i][j];
}
}
return result;
}
};
// @lc code=end
复杂度分析
时间复杂度:O(Amn),其中 m 和 n 分别为矩阵 image 的行数和列数,A=9 表示子网格大小。
空间复杂度:O(mn),其中 m 和 n 分别为矩阵 image 的行数和列数。
题目4:3031. 将单词恢复初始状态所需的最短时间 II
思路
代码
/*
* @lc app=leetcode.cn id=3031 lang=cpp
*
* [3031] 将单词恢复初始状态所需的最短时间 II
*/
// @lc code=start
// 暴力
// class Solution
// {
// public:
// int minimumTimeToInitialState(string word, int k)
// {
// string_view s = word; // 内存不溢出和不超时的关键
// int n = s.size();
// for (int t = 1, i = k; true; t++, i += k)
// if (i >= n || s.substr(i) == s.substr(0, n - i))
// return t;
// return -1;
// }
// };
// Z 函数算法(拓展 KMP)
class Solution
{
public:
int minimumTimeToInitialState(string s, int k)
{
int n = s.size();
vector<int> z(n);
int l = 0, r = 0;
for (int i = 1; i < n; i++)
{
if (i <= r)
{
z[i] = min(z[i - l], r - i + 1);
}
while (i + z[i] < n && s[z[i]] == s[i + z[i]])
{
l = i;
r = i + z[i];
z[i]++;
}
if (i % k == 0 && z[i] >= n - i)
{
return i / k;
}
}
return (n - 1) / k + 1;
}
};
// @lc code=end
复杂度分析
时间复杂度:O(n),其中 n 为字符串 s 的长度。
空间复杂度:O(n)。