LeetCode第 284 场周赛题解
6031. 找出数组中的所有 K 近邻下标
题目描述:给你一个下标从 \(0\) 开始的整数数组 \(nums\) 和两个整数 \(key\) 和 \(k\) 。\(k\) 近邻下标 是 \(nums\) 中的一个下标 \(i\) ,并满足至少存在一个下标\(j\) 使得 \(|i - j| \leq k\) 且 \(nums[j] == key\) 。
以列表形式返回按 递增顺序 排序的所有 \(k\) 近邻下标。
思路:考虑到\(n\)很小,直接暴力模拟即可
时间复杂度:\(O(n^2)\)
参考代码:
class Solution {
public:
vector<int> findKDistantIndices(vector<int>& nums, int key, int k) {
int n = nums.size();
vector<int>res;
for(int i = 0 ; i < n ; ++i){
for(int j = max(0 , i - k) ; j < min(n , i + k + 1) ; ++j){
if(nums[j] != key) continue;
res.push_back(i);
break;
}
}
return res;
}
};
5203. 统计可以提取的工件
题目描述:自己读题
思路:比较明显的二维前缀和,根据题意模拟即可
时间复杂度:\(O(n^2)\)
参考代码:
class Solution {
public:
int digArtifacts(int n, vector<vector<int>>& artifacts, vector<vector<int>>& dig) {
vector<vector<int>>grid(n + 1 , vector<int>(n + 1 , 0));
for(auto& vec : dig){
int u = vec[0] + 1, v = vec[1] + 1;
grid[u][v] = 1;
}
for(int i = 1 ; i <= n ; ++i){
for(int j = 1 ; j <= n ; ++j){
grid[i][j] = grid[i][j] + grid[i - 1][j] + grid[i][j - 1] - grid[i - 1][j - 1];
}
}
int res = 0;
for(auto& vec : artifacts){
int a = vec[0] + 1 , b = vec[1] + 1, c = vec[2] + 1, d = vec[3] + 1;
int sum = grid[c][d] - grid[c][b - 1] - grid[a - 1][d] + grid[a - 1][b - 1];
if(sum == (c - a + 1) * (d - b + 1)) ++res;
}
return res;
}
};
5227. K 次操作后最大化顶端元素
题目描述:给你一个下标从 \(0\) 开始的整数数组 \(nums\) ,它表示一个 栈 ,其中 \(nums[0]\) 是栈顶的元素。每一次操作中,你可以执行以下操作 之一 :
- 如果栈非空,那么 删除 栈顶端的元素。
- 如果存在 \(1\) 个或者多个被删除的元素,你可以从它们中选择任何一个,添加 回栈顶,这个元素成为新的栈顶元素。
同时给你一个整数 \(k\) ,它表示你总共需要执行操作的次数。
请你返回 恰好 执行 \(k\) 次操作以后,栈顶元素的 最大值 。如果执行完 \(k\) 次操作以后,栈一定为空,请你返回 \(-1\) 。
思路:根据题意模拟即可,对于当前栈顶数字,若拿起后,剩余操作次数为奇数或者剩余操作次数大于\(2\)且栈的总元素数量不为\(1\),说明该元素可以在最终出现在栈顶。注意特判\(k + 1\)。
时间复杂度:\(O(n)\)
参考代码:
class Solution {
public:
int maximumTop(vector<int>& nums, int k) {
int res = -1, n = nums.size();
reverse(nums.begin() , nums.end());
nums.push_back(0);
reverse(nums.begin() , nums.end());
for(int i = 1 ; i <= n ; ++i){
int dx = k - i;
if(dx % 2 == 1) res = max(res , nums[i]);
else if(dx >= 2 && n != 1) res = max(res , nums[i]);
}
if(k < n) res = max(res , nums[k + 1]);
return res;
}
};
6032. 得到要求路径的最小带权子图
题目描述:给定\(n\)个点\(m\)条边的有向图,求删除一些边之后使得删边之后的图权值和最小,且\(s1,s2\)都可以到达\(dest\)。求最小权值和,若不能满足条件,返回\(-1\)。
思路:定义\(dist_{i , j}\)表示从\(i\)出发到\(j\)的最短路径,那么答案为:
所以对\(s1,s2\)跑\(Dijkstra\),然后建立反向边以\(dest\)为起点跑\(Dijkstra\),然后枚举中间点取最小即可。
时间复杂度:\(O(mlogm)\)
参考代码:
class Solution {
public:
long long minimumWeight(int n, vector<vector<int>>& edges, int s1, int s2, int dest) {
using PLI = pair<long long, int>;
using PII = pair<int , int>;
vector<vector<PII>>graph(n), regraph(n);
vector<vector<int>>tr(n);
for (auto& edge : edges) {
int u = edge[0], v = edge[1], w = edge[2];
graph[u].push_back({ v , w });
regraph[v].push_back({u , w});
}
const long long MAXN = 0x3f3f3f3f3f3f3fll;
auto Dijkstra = [](vector<vector<PII>>& graph ,vector<long long>& dist, int st, int n) {
dist[st] = 0;
priority_queue<PLI, vector<PLI>, greater<PLI>>heap;
heap.push({ 0 , st });
vector<bool>vis(n, false);
while (!heap.empty()) {
auto [dis, ver] = heap.top();
heap.pop();
if (vis[ver]) continue;
vis[ver] = true;
for (auto&& [v, w] : graph[ver]) {
if (dist[v] > w + dis) {
dist[v] = w + dis;
heap.push({ dist[v] , v });
}
}
}
};
vector<long long>d1(n, MAXN), d2(n , MAXN) , d3(n , MAXN);
Dijkstra(graph , d1 , s1 , n);
Dijkstra(graph , d2 , s2 , n);
Dijkstra(regraph , d3 , dest , n);
if(d3[s1] == MAXN || d3[s2] == MAXN) return -1;
long long res = LLONG_MAX;
for(int i = 0 ; i < n ; ++i){
res = min(res , d1[i] + d2[i] + d3[i]);
}
return res;
}
};
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。