2023.3.19LeetCode第337场周赛
A. 奇偶位数
思路
枚举每一位是否为1
代码
class Solution {
public:
vector<int> evenOddBit(int n) {
vector<int> ans(2);
int f = 0;
while (n) {
if (n & 1) {
ans[f] ++ ;
}
f ^= 1;
n >>= 1;
}
return ans;
}
};
B. 检查骑士巡视方案
思路
将每个点的序号记录下来,按顺序检查相邻点之间是否可以到达
代码
typedef pair<int, int> PII;
#define x first
#define y second
class Solution {
public:
bool checkValidGrid(vector<vector<int>>& grid) {
vector<PII> a;
int n = grid.size();
a.resize(n * n);
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
a[grid[i][j]] = {i, j};
if (!(a[0].x == 0 && a[0].y == 0)) return false;
for (int i = 1; i < n * n; i ++ ) {
int x1 = a[i].x, y1 = a[i].y, x2 = a[i - 1].x, y2 = a[i - 1].y;
if (abs(x1 - x2) == 1 && abs(y1 - y2) == 2 || abs(x1 - x2) == 2 && abs(y1 - y2) == 1) continue;
return false;
}
return true;
}
};
C. 美丽子集的数目
思路
将所有数按照对k的余数相同的进行分组,只有同余的数才有可能互斥
先求出每一组中的美丽子集的数量,使用乘法原理相乘得到最后答案
求每一组中的数量可以使用动态规划,选和不选当前数
如果不选从前一个转移而来,如果选则要判断是否互斥,且要去除空集
代码
class Solution {
public:
int beautifulSubsets(vector<int>& nums, int k) {
unordered_map<int, map<int, int>> group; //分成同余的组
for (auto x : nums)
group[x % k][x] ++ ;
int ans = 1;
for (auto [_, g] : group) {
int n = g.size();
vector<int> f(n + 1);
auto it = g.begin();
f[0] = 1;
f[1] = (1 << it->second);
int la = it->first;
it ++ ;
for (int i = 2; i <= n; it ++ , i ++ ) {
f[i] = f[i - 1]; //不选当前数
if (it->first - la == k) //选当前数
f[i] += f[i - 2] * ((1 << it->second) - 1);
else
f[i] += f[i - 1] * ((1 << it->second) - 1);
la = it->first;
}
ans *= f[n]; //每个组的数量
}
return ans - 1; //减去空集
}
};
D. 执行操作后的最大 MEX
思路
负数x对m取余 (x % m + m) % m
记录所有元素的余数,从小到大枚举mex,直到数量不足就是答案
代码
class Solution {
public:
int findSmallestInteger(vector<int>& nums, int m) {
vector<int> cnt(m);
for (auto x : nums)
cnt[(x % m + m) % m] ++ ;
int ans = 0;
while (cnt[ans % m] -- ) {
ans ++ ;
}
return ans;
}
};