leetcode 第 387 场周赛 题解
100234. 在矩阵上写出字母 Y 所需的最少操作次数
简单题
class Solution {
public:
vector<int> resultArray(vector<int> &nums) {
int n = nums.size();
vector<int> v1, v2;
v1.emplace_back(nums[0]);
v2.emplace_back(nums[1]);
for (int i = 2; i < n; i++) {
if (v1.back() > v2.back()) {
v1.emplace_back(nums[i]);
} else {
v2.emplace_back(nums[i]);
}
}
v1.insert(v1.end(), v2.begin(), v2.end());
return v1;
}
};
100237. 元素和小于等于 k 的子矩阵的数目
预处理+bfs剪枝
class Solution {
public:
int countSubmatrices(vector<vector<int>> &grid, int k) {
queue<pair<int, int>> q;
int n = grid.size(), m = grid[0].size(), ans = 0;
// 初始化
int cal[n][m],vis[n][m];
memset(vis,0,sizeof(vis));
memset(cal,0,sizeof(cal));
// 预处理
cal[0][0] = grid[0][0];
for (int j = 1; j < m; ++j) {
cal[0][j] = grid[0][j] + cal[0][j - 1];
}
for (int i = 1; i < n; ++i) {
int res = 0;
for (int j = 0; j < m; ++j) {
res += grid[i][j];
cal[i][j] = res + cal[i - 1][j];
}
}
// bfs
q.emplace(0, 0);
while (!q.empty()) {
int x = q.front().first, y = q.front().second;
q.pop();
if (!vis[x][y] && cal[x][y] <= k) {
vis[x][y] = 1;
++ans;
if (x + 1 < n) q.emplace(x + 1, y);
if (y + 1 < m) q.emplace(x, y + 1);
}
}
return ans;
}
};
100234. 在矩阵上写出字母 Y 所需的最少操作次数
模拟
class Solution {
public:
int minimumOperationsToWriteY(vector<vector<int>> &grid) {
int n = grid.size(), mid = grid.size() / 2;
function<bool(int, int)> inY = [&](int x, int y) -> bool {
if (x <= mid && y <= mid && x == y) return true;
if (x < mid && y > mid && x + y == mid + mid) return true;
if (y == mid && x > mid) return true;
return false;
};
int cnt_Y[3], cnt_X[3];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (inY(i, j)) {
cnt_Y[grid[i][j]]++;
}
else cnt_X[grid[i][j]]++;
}
}
int sum_Y = n + n / 2, sum_X = n * n - sum_Y, ans = n*n;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; ++j) {
if (i == j) continue;
ans = min(ans, sum_Y - cnt_Y[i] + sum_X - cnt_X[j]);
}
}
return ans;
}
};
100246. 将元素分配到两个数组中 II
离散化+树状数组(单点更新,区域查询)
class Solution {
public:
struct Tree {
int n;
int c[100005];
Tree(int n) : n(n) {
memset(c, 0, sizeof(c));
}
int lowbit(int x) {
return x & (-x);
}
void add(int x, int val) { //在x位置加上val(是变化量),单点更新
while (x <= n) {
c[x] += val;
x += lowbit(x);
}
}
int getSum(int x) { //求c[1 - i]的和,区间查询
int res = 0;
while (x) {
res += c[x];
x -= lowbit(x);
}
return res;
}
};
vector<int> resultArray(vector<int> &nums) {
int n = nums.size();
vector<int> nums2(n), temp(nums);
// 离散化
// 排序
sort(temp.begin(), temp.end());
// 去重
temp.erase(unique(temp.begin(), temp.end()), temp.end());
for(int i:temp){
cout<<i<<" ";
}cout<<endl;
//寻找nums中每个值在排序之后的下标,转化为nums2
for (int i = 0; i < n; i++) {
nums2[i] = lower_bound(temp.begin(), temp.end(), nums[i]) - temp.begin() + 1;
}
int len = temp.size();
//开始按照题目要求进行模拟
vector<int> v1, v2;
v1.emplace_back(nums2[0]);
v2.emplace_back(nums2[1]);
Tree tree1(len + 1), tree2(len + 1);
tree1.add(nums2[0], 1);
tree2.add(nums2[1], 1);
for (int i = 2; i < n; i++) {
int n1 = v1.size(), n2 = v2.size();
//总数减去小于等于的元素数目就是大于的元素数目
int sum1 = n1 - tree1.getSum(nums2[i]), sum2 = n2 - tree2.getSum(nums2[i]);
//按照规则分类
if (sum1 > sum2 || (sum1 == sum2 && n1 <= n2)) {
v1.emplace_back(nums2[i]);
tree1.add(nums2[i], 1);
} else {
v2.emplace_back(nums2[i]);
tree2.add(nums2[i], 1);
}
}
v1.insert(v1.end(), v2.begin(), v2.end());
for (int i: v1) {
i = temp[i - 1];
}
return v1;
}
};