周赛传送门
5843. 作为子字符串出现在单词中的字符串数目
思路:std::string::find
时间复杂度:, 为 的字符总数, 为 的字符总数。
根据 std::string::find 返回值是否等于std::string::npos,可以快速判断 是否为 的子串。
class Solution {
public:
int numOfStrings(vector<string>& patterns, string word) {
int cnt = 0;
for (const auto & c : patterns) {
if (word.find(c) != std::string::npos) {
cnt++;
}
}
return cnt;
}
};
5832. 构造元素不等于两相邻元素平均值的数组
思路:排序,交换
时间复杂度:
考虑一个下标从 开始的,严格递增的序列 。将其中 的元素 与 进行交换。交换后:
- 处均满足
- 处均满足
显然,交换后任意位置均满足要求。因此,可先对 进行排序,然后按上述流程处理。
class Solution {
public:
vector<int> rearrangeArray(vector<int>& nums) {
sort(nums.begin(), nums.end());
for (int i = 2; i < nums.size(); i += 2) {
swap(nums[i-1], nums[i]);
}
return nums;
}
};
5844. 数组元素的最小非零乘积
思路:贪心,快速幂
时间复杂度:
首先思考怎样交换才能使乘积变小。
设有两个整数 ,,交换第 位的值。如果 和 的第 位的值相同,则操作无意义。因此只考虑第位不同的情形,假设交换前:
则交换后的乘积为:
对比交换前的乘积 ,需满足:
总结一下:只要数组中存在两个整数 和 ,且存在 ,满足 ,,且 ,则通过交换 和 的 第 位即可减小乘积。
反过来想,如果数组中不存在这样的 和 ,则就达到了最小的乘积。
先考虑 区间内的数字,我们可将这 个数字分成 对,每队数字 均满足 。
注意, 是个很特殊的数字,是由 个 组成的。
换言之,如果 ,则对于任意 ,均有。那么,若 满足 ,则其最小非零乘积为 。即:
将每一对 都置为 ,则此时我们共有 个数,分别为:
受限于「」 以及 「非零乘积」两个要求,此时无法再进行交换了。因此最终答案为:
class Solution {
public:
const int64_t MOD = 1e9+7;
int64_t pow(int64_t e, int64_t p, int64_t mod = std::numeric_limits<int64_t>::max()) {
if (p == 0) { return 1; }
if (p == 1) { return e%mod; }
int64_t m = pow(e, p/2, mod);
return m*m%mod * ((p&1) ? e%mod : 1) % mod;
}
int minNonZeroProduct(int p) {
int64_t anw = 1;
(anw *= (pow(2, p) - 1)) %= MOD;
(anw *= pow(pow(2, p) - 2, pow(2, p-1)-1, MOD)) %= MOD;
return anw;
}
};
5845. 你能穿过矩阵的最后一天
思路:二分,广度优先遍历
时间复杂度:, 为格子总数
如果第 天能从第一行走到最后一行,那么前天也可以,因为之前天的陆地更多。
如果第 天不能从第一行走到最后一行,那么之后的每一天也不能,因为陆地在不断减少。
显然,满足二分的条件,上限为 ,下限为 。
对于二分的每一个值 ,此时地图中仅 ,,... 处变为了水域。然后判断是否有从第一行到最后一行的路径即可,或者判断是否有从第一列到最后一列的淹水区域也可。
class Solution {
public:
bool check(int r, int c, const vector<vector<int>> &cell, int n) {
vector<vector<bool>> mark(r, vector<bool>(c, false));
queue<pair<int, int>> q;
for (int i = 0; i < n; i++) {
int x = cell[i][0]-1;
int y = cell[i][1]-1;
if (y == 0) {
q.push(make_pair(x,y));
} else {
mark[x][y] = true;
}
}
while(!q.empty()) {
auto f = q.front();
q.pop();
if (f.second == c-1) {
return true;
}
int dx[] = {-1, 0, 1, 0, -1, -1, 1, 1};
int dy[] = { 0, -1, 0, 1, -1, 1,-1, 1};
for (int i = 0; i < 8; i++) {
int nx = f.first + dx[i];
int ny = f.second + dy[i];
if (0 <= nx && nx < r && 0 <= ny && ny < c && mark[nx][ny]) {
mark[nx][ny] = false;
q.push(make_pair(nx, ny));
}
}
}
return false;
}
int latestDayToCross(int row, int col, vector<vector<int>>& cells) {
int L = 0, R = cells.size()-1;
while (L <= R) {
int mid = (L+R)/2;
if (check(row, col, cells, mid) == false) {
L = mid+1;
} else {
R = mid-1;
}
}
return L-1;
}
};