2023.4.9LeetCode第340场周赛
A. 对角线上的质数
思路
枚举所有对角线上的数,判断是否为质数
使用
O
(
n
)
O(\sqrt n)
O(n)的算法判断质数
判断x是否为质数,若x=a*b,只用考虑a<=b的情况,故只用枚举到
n
\sqrt{n}
n
代码
class Solution {
public:
bool isp(int x) {
if (x == 1) return false;
for (int i = 2; i * i <= x; i ++ ) {
if (x % i == 0)
return false;
}
return true;
}
int diagonalPrime(vector<vector<int>>& a) {
int m = a.size();
int ans = 0;
for (int i = 0; i < m; i ++ ) {
if (isp(a[i][i]))
ans = max(ans, a[i][i]);
if (isp(a[i][m - i - 1]))
ans = max(ans, a[i][m - i - 1]);
}
return ans;
}
};
B. 等值距离和
思路
将所有数按照相同元素分组
枚举每个组,计算绝对值之和时数组是有序的,可以分为前半部分和后半部分,设当前数为x,前半部分x较大,绝对值和为(x*前半部分的数量-前半部分的前缀和),后半部分x较小,绝对值和为(后半部分的前缀和 - x*后半部分的数量),两部分的前缀和分别用两个变量维护
代码
class Solution {
public:
typedef long long ll;
vector<long long> distance(vector<int>& a) {
unordered_map<int, vector<int>> mp;
int n = a.size();
for (int i = 0; i < n; i ++ ) {
mp[a[i]].push_back(i);
}
vector<ll> ans(n);
for (auto& [k, v] : mp) {
int m = v.size();
if (m == 1) continue;
ll s = 0;
for (int i = 0; i < m; i ++ )
s += v[i];
ll t = 0;
for (int i = 0; i < m; i ++ ) {
s -= v[i];
ans[v[i]] = ((ll)v[i] * i) - t + (s - (ll)v[i] * (m - i - 1));
t += v[i];
}
}
return ans;
}
};
C. 最小化数对的最大差值
思路
二分,答案越大越能满足,越小越不能满足,具有二分性
使用贪心的策略判断,将数组排序后尽量选择相邻的两个数,满足条件向后移动两位,不满足则向后移动一位
代码
class Solution {
public:
int minimizeMax(vector<int>& a, int p) {
sort(a.begin(), a.end());
int n = a.size();
int l = 0, r = 1e9;
while (l < r) {
int mid = l + r >> 1;
if (check(mid, a, p)) r = mid;
else l = mid + 1;
}
return l;
}
bool check(int x, vector<int>& a, int p) {
int t = p;
for (int i = 0; i + 1 < a.size();) {
if (a[i + 1] - a[i] <= x) {
p -- ;
i += 2;
} else i ++ ;
}
return p <= 0;
}
};
D. 网格图中最少访问的格子数
思路
优先队列,给每一列和每一行都维护一个优先队列,枚举每个点时,考虑可以从上面或者左边走过来,选择两个方向上的最优情况,即堆顶元素,若不能走到当前点,从堆中去除
代码
#define x first
#define y second
class Solution {
public:
typedef pair<int, int> PII;
int minimumVisitedCells(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
vector<priority_queue<PII, vector<PII>, greater<PII>>> row(n), col(m);
vector<vector<int>> d(n, vector<int>(m, -1));
d[0][0] = 1;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < m; j ++ ) {
//从左边来
while (row[i].size() && row[i].top().y + grid[i][row[i].top().y] < j) {
row[i].pop();
}
if (row[i].size()) {
d[i][j] = d[i][row[i].top().y] + 1;
}
//从上面来
while (col[j].size() && col[j].top().y + grid[col[j].top().y][j] < i) {
col[j].pop();
}
if (col[j].size()) {
if (d[i][j] != -1)
d[i][j] = min(d[i][j], d[col[j].top().y][j] + 1);
else
d[i][j] = d[col[j].top().y][j] + 1;
}
if (d[i][j] != -1) {
row[i].push({d[i][j], j});
col[j].push({d[i][j], i});
}
}
return d[n - 1][m - 1];
}
};