LeetCode第 67 场双周赛
T1 5934. 找到和最大的长度为 K 的子序列
题目描述: 找到长度为\(k\)的和最大子序列
思路:记录一下下标排序之后选出最大的\(k\)个,然后再排序回去即可。
时间复杂度:\(O(nlogn)\)
参考代码:
class Solution {
public:
vector<int> maxSubsequence(vector<int>& nums, int k) {
vector<pair<int , int>> a;
int n = nums.size();
for(int i = 0 ; i < n ; ++i) a.push_back({nums[i] , i});
sort(a.begin() , a.end());
vector<pair<int, int>> b;
for(int i = n - 1 ; i >= n - k ; --i) b.push_back({a[i].second , a[i].first});
vector<int>res;
sort(b.begin() , b.end());
for(auto num : b) res.push_back(num.second);
return res;
}
};
T2 5935. 适合打劫银行的日子
题目描述:给定\(time\),求出所有满足下述条件的下标
思路:经典题目,顺着\(dp\)一遍求到当前位置的最长非递增子数组长度,倒着\(dp\)一遍求到当前位置的最长非递减子数组的长度。然后枚举判断即可。
定义\(f_i\)表示从前往后,\(g_i\)表示从后往前,则转移方程为
时间复杂度:\(O(n)\)
参考代码:
class Solution {
public:
vector<int> goodDaysToRobBank(vector<int>& a, int time) {
int n = a.size();
vector<int>f(n + 2 , 0) , g(n + 2 , 0);
f[1] = 1;
for(int i = 1 ; i < n ; ++i){
f[i + 1] = 1;
if(a[i] <= a[i - 1]) f[i + 1] += f[i];
}
g[n] = 1;
for(int i = n - 2 ; i >= 0 ; --i){
g[i + 1] = 1;
if(a[i] <= a[i + 1]) g[i + 1] += g[i + 2];
}
vector<int>res;
for(int i = time + 1 ; i <= n - time ; ++i)
if(f[i] > time && g[i] > time) res.push_back(i - 1);
return res;
}
};
T3 5936. 引爆最多的炸弹
题目描述:给定\(n\)个炸弹,每个炸弹爆炸的同时会引爆在其爆炸范围内的炸弹,问你引爆其中一个炸弹时,实际爆炸的炸弹的总数目最大是多少。
思路:考虑建图,当两个炸弹之间的距离小于等于该炸弹的引爆范围时,建立一条从该炸弹到另一个炸弹的有向边,建好图之后,以每一个炸弹作为起点进行dfs,统计能访问到的点的数目,就是引爆该点炸弹时实际能引爆的炸弹数,取最大即可。
时间复杂度:\(O(n^2)\)
参考代码:
class Solution {
private:
long long cal(vector<int>& a , vector<int>& b){
return 1ll * (a[0] - b[0]) * (a[0] - b[0]) + 1ll * (a[1] - b[1]) * (a[1] - b[1]);
}
void dfs(vector<vector<int>>& graph , int u , int& cnt, vector<int>& vis){
if(vis[u] == 1) return ;
++cnt;
vis[u] = 1;
for(auto v : graph[u]) dfs(graph , v , cnt , vis);
return ;
}
public:
int maximumDetonation(vector<vector<int>>& bombs) {
int n = bombs.size();
vector<vector<int>>graph(n);
for(int i = 0 ; i < n ; ++i){
for(int j = i + 1 ; j < n ; ++j){
long long dis = cal(bombs[i] , bombs[j]);
if(dis <= 1ll * bombs[i][2] * bombs[i][2]) graph[i].push_back(j);
if(dis <= 1ll * bombs[j][2] * bombs[j][2]) graph[j].push_back(i);
}
}
vector<int>vis(n , 0);
int res = 0;
for(int i = 0 ; i < n ; ++i){
int cnt = 0;
dfs(graph , i , cnt, vis);
vis = vector<int>(n , 0);
res = max(res , cnt);
}
return res;
}
};
T4 5937. 序列顺序查询
题目描述:你需要实现一个类,该类具有以下功能:
- 插入一个字符串和该字符串的\(score\)
- 询问插入的所有字符串中,第\(k\)好的是什么
一个字符串比另一个字符串好当且仅当该字符串的\(score\)大于另一个字符串的\(score\)或者两者的\(score\)相同但一个字符串的字典序比另一个字符串的字典序小。
询问的参数\(k\)是根据当前询问的次数来定的,比如我第一次询问,\(k = 1\),第二次询问,则\(k = 2\),依次类推
思路:经典题目,考虑维护俩堆,一个小根堆,一个大根堆,小根堆的堆顶元素就是下次要询问的答案,大根堆用于在询问后将小根堆的元素数量\(+1\)。
C++考虑使用set进行维护即可。
时间复杂度:\(O(nlogn)\)
C++参考代码:
class SORTracker {
private:
struct infor{
int val;
string name;
bool operator < (const infor& a)const{
return val < a.val || (val == a.val && name > a.name);
}
};
set<infor> s , t;
int cur;
public:
SORTracker() {
cur = 0;
}
void add(string name, int score) {
if(s.size() == 0 || s.size() < cur + 1) s.insert({score , name});
else{
auto [sc , na] = *s.begin();
if(sc < score || (sc == score && name < na)) {
t.insert(*s.begin()) ;
s.erase(s.begin()) ;
s.insert({score , name});
}
else t.insert({score , name});
}
return ;
}
string get() {
string res = (*s.begin()).name;
++cur;
if(t.size() != 0){
s.insert(*t.rbegin());
t.erase(*t.rbegin());
}
return res;
}
};
Java参考代码:
class SORTracker {
class infor{
int val;
String name;
infor(int val , String name){
this.val = val;
this.name = name;
}
}
private PriorityQueue<infor> heap1, heap2;
private int cnt;
public SORTracker() {
heap1 = new PriorityQueue<infor>((a , b)->{
if(a.val != b.val) return a.val - b.val;
return b.name.compareTo(a.name);
});
heap2 = new PriorityQueue<infor>((a , b)->{
if(a.val != b.val) return b.val - a.val;
return a.name.compareTo(b.name);
});
}
public void add(String name, int score) {
if(heap1.size() < cnt + 1) heap1.add(new infor(score , name));
else{
infor a = heap1.poll();
if(a.val < score || (a.val == score && name.compareTo(a.name) < 0)){
heap1.add(new infor(score , name));
heap2.add(a);
}
else{
heap1.add(a);
heap2.add(new infor(score , name));
}
}
}
public String get() {
++cnt;
String res = heap1.peek().name;
if(!heap2.isEmpty())heap1.add(heap2.poll());
return res;
}
}
推荐题目:
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。