LeetCode biweekly-contest-67

LeetCode biweekly-contest-67

今天加班了一天,回家已经好累了,洗个澡精神一下继续冲题了,不知道是不是题目比较简单还是自己提高了,状态这么差每道题还都有思路,第二道题和第四道题超时了,实在没脑子了,第一次进1000,排名711 / 2923

5934. 找到和最大的长度为 K 的子序列[EASY]

给你一个整数数组 nums 和一个整数 k 。你需要找到 nums 中长度为 k 的 子序列 ,且这个子序列的 和最大 。

请你返回 任意 一个长度为 k 的整数子序列。

子序列 定义为从一个数组里删除一些元素后,不改变剩下元素的顺序得到的数组。

示例 1:
输入:nums = [2,1,3,3], k = 2
输出:[3,3]
解释:
子序列有最大和:3 + 3 = 6 。

示例 2:
输入:nums = [-1,-2,3,4], k = 3
输出:[-1,3,4]
解释:
子序列有最大和:-1 + 3 + 4 = 6 。

示例 3:
输入:nums = [3,4,3,3], k = 2
输出:[3,4]
解释:
子序列有最大和:3 + 4 = 7 。
另一个可行的子序列为 [4, 3] 。

提示:
1 <= nums.length <= 1000
-105 <= nums[i] <= 105
1 <= k <= nums.length

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/* 
审题:
这题搞复杂了,当时脑子的思路是
1. 先push index和value
2. 对value排个序
3. 取出前k个index和value的pair
4. 再对index排序

实际可以这样
1. push index和value
2. 直接对value和index排序,value从大到小,index从小到大
这样直接输出就ok了
*/
class Solution {
public:
vector<int> maxSubsequence(vector<int>& nums, int k) {
vector<vector<int>> indexValue(nums.size(), vector<int>(2, 0));
for (int i = 0; i < nums.size(); i++) {
indexValue[i][0] = i;
indexValue[i][1] = nums[i];
}
sort(indexValue.begin(), indexValue.end(), [](const vector<int>& x, const vector<int>& y) {
return x[1] > y[1];
});
// for (auto& i : indexValue) {
// cout << i[0] << ", " << i[1] << endl;
// }
vector<vector<int>> res(k, vector<int>());
for (int i = 0; i < k; i++) {
res[i] = indexValue[i];
}
sort(res.begin(), res.end(), [](const vector<int>& x, const vector<int>& y) {
return x[0] < y[0];
});
vector<int> result(k);
for (int i = 0; i < k; i++) {
result[i] = res[i][1];
}
return result;
}
};

5935. 适合打劫银行的日子 [MEDIUM]

你和一群强盗准备打劫银行。给你一个下标从 0 开始的整数数组 security ,其中 security[i] 是第 i 天执勤警卫的数量。日子从 0 开始编号。同时给你一个整数 time 。

如果第 i 天满足以下所有条件,我们称它为一个适合打劫银行的日子:

第 i 天前和后都分别至少有 time 天。
第 i 天前连续 time 天警卫数目都是非递增的。
第 i 天后连续 time 天警卫数目都是非递减的。
更正式的,第 i 天是一个合适打劫银行的日子当且仅当:security[i - time] >= security[i - time + 1] >= … >= security[i] <= … <= security[i + time - 1] <= security[i + time].

请你返回一个数组,包含 所有 适合打劫银行的日子(下标从 0 开始)。返回的日子可以 任意 顺序排列。

示例 1:
输入:security = [5,3,3,3,5,6,2], time = 2
输出:[2,3]
解释:
第 2 天,我们有 security[0] >= security[1] >= security[2] <= security[3] <= security[4] 。
第 3 天,我们有 security[1] >= security[2] >= security[3] <= security[4] <= security[5] 。
没有其他日子符合这个条件,所以日子 2 和 3 是适合打劫银行的日子。

示例 2:
输入:security = [1,1,1,1,1], time = 0
输出:[0,1,2,3,4]
解释:
因为 time 等于 0 ,所以每一天都是适合打劫银行的日子,所以返回每一天。

示例 3:
输入:security = [1,2,3,4,5,6], time = 2
输出:[]
解释:
没有任何一天的前 2 天警卫数目是非递增的。
所以没有适合打劫银行的日子,返回空数组。

示例 4:
输入:security = [1], time = 5
输出:[]
解释:
没有日子前面和后面有 5 天时间。
所以没有适合打劫银行的日子,返回空数组。

提示:
1 <= security.length <= 105
0 <= security[i], time <= 105

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/*
审题:银行出的题搞了个打劫的题目,也是挺搞笑的。先写了一道暴力破解的题,果不其然超时了(心存侥幸)。后面想到了一种方法:
1. 从左到右遍历一遍,动态拿到每个位置的最大
2. 从右到左遍历一遍,动态拿到每个位置的最大递减(从左到右看就是递增)
3. 再遍历一遍,找到左右的最大递增递减的长度大于time的
*/
class Solution {
public:
inline bool isGoodRobDay(int i, vector<int>& security, int time)
{
int minimum = INT_MAX;
for (int day = i - time; day <= i; day++) {
if (security[day] <= minimum) {
minimum = security[day];
} else {
return false;
}
}
int maximum = -INT_MAX;
for (int day = i; day <= i + time; day++) {
if (security[day] >= maximum) {
maximum = security[day];
} else {
return false;
}
}
return true;
}
vector<int> goodDaysToRobBank(vector<int>& security, int time) {
int days = security.size();
vector<int> result;
for (int i = time; i < days - time; i++) {
if (isGoodRobDay(i, security, time)) {
result.emplace_back(i);
}
}
return result;
}
};

5936. 引爆最多的炸弹[MEDIUM]

给你一个炸弹列表。一个炸弹的 爆炸范围 定义为以炸弹为圆心的一个圆。

炸弹用一个下标从 0 开始的二维整数数组 bombs 表示,其中 bombs[i] = [xi, yi, ri] 。xi 和 yi 表示第 i 个炸弹的 X 和 Y 坐标,ri 表示爆炸范围的 半径 。

你需要选择引爆 一个 炸弹。当这个炸弹被引爆时,所有 在它爆炸范围内的炸弹都会被引爆,这些炸弹会进一步将它们爆炸范围内的其他炸弹引爆。

给你数组 bombs ,请你返回在引爆 一个 炸弹的前提下,最多 能引爆的炸弹数目。

示例 1:
输入:bombs = [[2,1,3],[6,1,4]]
输出:2
解释:
上图展示了 2 个炸弹的位置和爆炸范围。
如果我们引爆左边的炸弹,右边的炸弹不会被影响。
但如果我们引爆右边的炸弹,两个炸弹都会爆炸。
所以最多能引爆的炸弹数目是 max(1, 2) = 2 。

示例 2:
输入:bombs = [[1,1,5],[10,10,5]]
输出:1
解释:
引爆任意一个炸弹都不会引爆另一个炸弹。所以最多能引爆的炸弹数目为 1 。

示例 3:
输入:bombs = [[1,2,3],[2,3,1],[3,4,2],[4,5,3],[5,6,4]]
输出:5
解释:
最佳引爆炸弹为炸弹 0 ,因为:

  • 炸弹 0 引爆炸弹 1 和 2 。红色圆表示炸弹 0 的爆炸范围。
  • 炸弹 2 引爆炸弹 3 。蓝色圆表示炸弹 2 的爆炸范围。
  • 炸弹 3 引爆炸弹 4 。绿色圆表示炸弹 3 的爆炸范围。
    所以总共有 5 个炸弹被引爆。

提示:
1 <= bombs.length <= 100
bombs[i].length == 3
1 <= xi, yi, ri <= 105

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
审题:这题做出来很开心,因为之前碰到BFS的题除了二叉树层序遍历都没做出来过(又想起在学校实习面微软3面就差BFS做出来了,可惜可恨,人生轨迹都变了)。回到正题,这题思路这样的:
1. 计算每个炸弹是否能炸到其他炸弹,存个矩阵
2. 遍历每个炸弹
3. 用BFS,能炸到的不重复的炸弹放进stack里面,每次pop一个看它还能不能炸到其他不重复的炸弹,直到stack为空

#include <cmath>
#include <stack>
class Solution {
public:
int BFS(int i, vector<vector<int>>& bombMap, vector<vector<int>>& bombs)
{
int m = bombs.size();
stack<int> bombStack;
bombStack.push(i);
int number = 0;
vector<bool> visited(m, false);
while (!bombStack.empty()) {
int top = bombStack.top();
bombStack.pop();
if (visited[top]) {
continue;
}
number++;
visited[top] = true;
for (int k = 0; k < m; k++) {
if (bombMap[top][k]) {
bombStack.push(k);
}
}
}
return number;
}

int maximumDetonation(vector<vector<int>>& bombs) {
int m = bombs.size();
vector<vector<int>> bombMap(m, vector<int>(m, 0));
for (int i = 0; i < m; i++) {
for (int j = i + 1; j < m; j++) {
double x = (bombs[i][0] - bombs[j][0]);
double y = (bombs[i][1] - bombs[j][1]);
double distance = sqrt(x * x + y * y);
if (distance <= bombs[i][2]) {
bombMap[i][j] = 1;
}
if (distance <= bombs[j][2]) {
bombMap[j][i] = 1;
}
}
}

int maxBomb = 0;
for (int i = 0; i < m; i++) {
int numBomb = BFS(i, bombMap, bombs);
// cout << "numbBomb " << numBomb << endl;
if (numBomb > maxBomb) {
maxBomb = numBomb;
}
}

// for (auto& bomb : bombMap) {
// for (auto& dis : bomb) {
// cout << dis << ", ";
// }
// cout << endl;
// }
return maxBomb;
}
};

5937. 序列顺序查询 [HARD]

一个观光景点由它的名字 name 和景点评分 score 组成,其中 name 是所有观光景点中 唯一 的字符串,score 是一个整数。景点按照最好到最坏排序。景点评分 越高 ,这个景点越好。如果有两个景点的评分一样,那么 字典序较小 的景点更好。

你需要搭建一个系统,查询景点的排名。初始时系统里没有任何景点。这个系统支持:

添加 景点,每次添加 一个 景点。
查询 已经添加景点中第 i 好 的景点,其中 i 是系统目前位置查询的次数(包括当前这一次)。
比方说,如果系统正在进行第 4 次查询,那么需要返回所有已经添加景点中第 4 好的。
注意,测试数据保证 任意查询时刻 ,查询次数都 不超过 系统中景点的数目。

请你实现 SORTracker 类:

SORTracker() 初始化系统。
void add(string name, int score) 向系统中添加一个名为 name 评分为 score 的景点。
string get() 查询第 i 好的景点,其中 i 是目前系统查询的次数(包括当前这次查询)。

示例:

输入:

1
2
3
4
["SORTracker", "add", "add", "get", "add", "get", "add", "get", "add", "get", "add", "get", "get"]
[[], ["bradford", 2], ["branford", 3], [], ["alps", 2], [], ["orland", 2], [], ["orlando", 3], [], ["alpine", 2], [], [\]]
输出:
[null, null, null, "branford", null, "alps", null, "bradford", null, "bradford", null, "bradford", "orland"]

解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SORTracker tracker = new SORTracker(); // 初始化系统
tracker.add("bradford", 2); // 添加 name="bradford" 且 score=2 的景点。
tracker.add("branford", 3); // 添加 name="branford" 且 score=3 的景点。
tracker.get(); // 从好带坏的景点为:branford ,bradford 。
// 注意到 branford 比 bradford 好,因为它的 评分更高 (3 > 2) 。
// 这是第 1 次调用 get() ,所以返回最好的景点:"branford" 。
tracker.add("alps", 2); // 添加 name="alps" 且 score=2 的景点。
tracker.get(); // 从好到坏的景点为:branford, alps, bradford 。
// 注意 alps 比 bradford 好,虽然它们评分相同,都为 2 。
// 这是因为 "alps" 字典序 比 "bradford" 小。
// 返回第 2 好的地点 "alps" ,因为当前为第 2 次调用 get() 。
tracker.add("orland", 2); // 添加 name="orland" 且 score=2 的景点。
tracker.get(); // 从好到坏的景点为:branford, alps, bradford, orland 。
// 返回 "bradford" ,因为当前为第 3 次调用 get() 。
tracker.add("orlando", 3); // 添加 name="orlando" 且 score=3 的景点。
tracker.get(); // 从好到坏的景点为:branford, orlando, alps, bradford, orland 。
// 返回 "bradford".
tracker.add("alpine", 2); // 添加 name="alpine" 且 score=2 的景点。
tracker.get(); // 从好到坏的景点为:branford, orlando, alpine, alps, bradford, orland 。
// 返回 "bradford" 。
tracker.get(); // 从好到坏的景点为:branford, orlando, alpine, alps, bradford, orland 。
// 返回 "orland" 。

提示:

name 只包含小写英文字母,且每个景点名字互不相同。
1 <= name.length <= 10
1 <= score <= 105
任意时刻,调用 get 的次数都不超过调用 add 的次数。
总共 调用 add 和 get 不超过 4 * 104

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
审题:这题系统题,基本都是考数据结构,不懂为啥会超时,可能是vector insert的时候需要移动元素太慢了吧,应该用个可以排序的非连续存储的数据结构比如set或者hashmap之类的就可以

class SORTracker {
public:
SORTracker() {
sites_.resize(4e4 + 1);
}

void add(string name, int score) {
// auto pos = std::lower_bound(sites_.begin(), sites_.end(), make_pair(name, score),
// [](const pair<string, int>& x, const pair<string, int>& y) {
// if (x.second != y.second) {
// return x.second > y.second;
// } else {
// return x.first < y.first;
// }
// });
// sites_.insert(pos, make_pair(name, score));
sites_.emplace_back(make_pair(name, score));
}

string get() {
sort(sites_.begin(), sites_.end(),
[](const pair<string, int>& x, const pair<string, int>& y) {
if (x.second != y.second) {
return x.second > y.second;
} else {
return x.first < y.first;
}
});
return sites_[currentQuery_++].first;

}

private:

int currentQuery_{0};

vector<pair<string, int>> sites_;

};

/**
* Your SORTracker object will be instantiated and called as such:
* SORTracker* obj = new SORTracker();
* obj->add(name,score);
* string param_2 = obj->get();
*/
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×