leetcode contest 312
leetcode contest 312
周赛题目质量不错的一次,不过排名也100往后了,还是思路不够快。
6188. 按身高排序
题目
给你一个字符串数组 names ,和一个由 互不相同 的正整数组成的数组heights 。两个数组的长度均为 n 。
对于每个下标 i,names[i] 和 heights[i] 表示第 i 个人的名字和身高。
请按身高 降序 顺序返回对应的名字数组 names 。
示例 1:1
2
3输入:names = ["Mary","John","Emma"], heights = [180,165,170]
输出:["Mary","Emma","John"]
解释:Mary 最高,接着是 Emma 和 John 。
示例 2:1
2
3输入:names = ["Alice","Bob","Bob"], heights = [155,185,150]
输出:["Bob","Alice","Bob"]
解释:第一个 Bob 最高,然后是 Alice 和第二个 Bob 。
提示:
n == names.length == heights.length1 <= n <= 1031 <= names[i].length <= 201 <= heights[i] <= 105names[i]由大小写英文字母组成heights中的所有值互不相同
地址
https://leetcode.cn/contest/weekly-contest-312/problems/sort-the-people/
题意
排序
思路
- 按照题目要求进行排序即可。
- 复杂度分析:
- 时间复杂度:$O(n \log n)$,其中 $n$ 表示数组的长度。
- 空间复杂度:$O(n \log n)$,其中 $n$ 表示数组的长度。
代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Solution {
public:
vector<string> sortPeople(vector<string>& names, vector<int>& heights) {
vector<pair<string, int>> arr;
for (int i = 0; i < names.size(); i++) {
arr.emplace_back(names[i], heights[i]);
}
sort(arr.begin(), arr.end(), [](const pair<string, int> &a, const pair<string, int> &b) {
return a.second > b.second;
});
vector<string> ans;
for (auto [name, _] : arr) {
ans.emplace_back(name);
}
return ans;
}
};
6189. 按位与最大的最长子数组
题目
给你一个长度为 n 的整数数组 nums 。
考虑 nums 中进行 按位与(bitwise AND)运算得到的值 最大 的 非空 子数组。
换句话说,令 k 是 nums 任意 子数组执行按位与运算所能得到的最大值。那么,只需要考虑那些执行一次按位与运算后等于 k 的子数组。
返回满足要求的 最长 子数组的长度。
数组的按位与就是对数组中的所有数字进行按位与运算。
子数组 是数组中的一个连续元素序列。
示例 1:1
2
3
4
5输入:nums = [1,2,3,3,2,2]
输出:2
解释:
子数组按位与运算的最大值是 3 。
能得到此结果的最长子数组是 [3,3],所以返回 2 。
示例 2:1
2
3
4
5输入:nums = [1,2,3,4]
输出:1
解释:
子数组按位与运算的最大值是 4 。
能得到此结果的最长子数组是 [4],所以返回 1 。
提示:
1 <= nums.length <= 1051 <= nums[i] <= 106
地址
https://leetcode.cn/contest/cnunionpay2022/problems/6olJmJ/
题意
数学
思路
- 连续子数组与运算的最大值即为数组的最大值 $maxV$,数组的最大值与上任何元素的结果均小于等于它本身,因此我们的目标即为找到连续 $maxV$ 的最大长度即可。
- 复杂度分析:
1 | |
6190. 找到所有好下标
题目
给你一个大小为 n 下标从 0 开始的整数数组 nums 和一个正整数 k 。
对于 k <= i < n - k 之间的一个下标 i ,如果它满足以下条件,我们就称它为一个 好 下标:
- 下标
i之前 的k个元素是 非递增的 。 - 下标
i之后 的k个元素是 非递减的 。
按 升序 返回所有好下标。
示例 1:1
2
3
4
5
6输入:nums = [2,1,1,1,3,4,1], k = 2
输出:[2,3]
解释:数组中有两个好下标:
- 下标 2 。子数组 [2,1] 是非递增的,子数组 [1,3] 是非递减的。
- 下标 3 。子数组 [1,1] 是非递增的,子数组 [3,4] 是非递减的。
注意,下标 4 不是好下标,因为 [4,1] 不是非递减的。
示例 2:1
2
3输入:nums = [2,1,1,2], k = 2
输出:[]
解释:数组中没有好下标。
提示:
n == nums.length3 <= n <= 1051 <= nums[i] <= 1061 <= k <= n / 2
地址
https://leetcode.cn/contest/weekly-contest-312/problems/find-all-good-indices/
题意
滑动窗口
思路
- 题目本身比较简单,对于每个位置的 $i$,我们找到 $i$ 的左侧连续非递增的最大长度为 $left[i]$,我们找到 $i$ 的右侧连续非递减的最大长度为 $right[i]$,对于每个索引 $i$ 处,只需要满足:则索引 $i$ 即可满足要求。
- 复杂度分析
- 时间复杂度:时间复杂度为 $O(n)$,$n$ 为数组的长度。
- 空间复杂度:时间复杂度为 $O(n)$,$n$ 为数组的长度。
代码
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
28class Solution {
public:
vector<int> goodIndices(vector<int>& nums, int k) {
int n = nums.size();
vector<int> left(n, 1), right(n, 1);
for (int i = 1; i < n; i++) {
if (nums[i] > nums[i-1]) {
left[i] = 1;
} else {
left[i] = left[i - 1] + 1;
}
}
for (int i = n - 2; i >= 0; i--) {
if (nums[i] > nums[i+1]) {
right[i] = 1;
} else {
right[i] = right[i + 1] + 1;
}
}
vector<int> ans;
for (int i = k; i < n - k; i++) {
if (left[i - 1] >= k && right[i + 1] >= k) {
ans.emplace_back(i);
}
}
return ans;
}
};
6191. 好路径的数目
题目
给你一棵 n个节点的树(连通无向无环的图),节点编号从 0 到 n - 1 且恰好有 n - 1 条边。
给你一个长度为 n 下标从 0 开始的整数数组 vals ,分别表示每个节点的值。同时给你一个二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 ai 和 bi 之间有一条 无向 边。
一条 好路径 需要满足以下条件:
- 开始节点和结束节点的值 相同 。
- 开始节点和结束节点中间的所有节点值都 小于等于 开始节点的值(也就是说开始节点的值应该是路径上所有节点的最大值)。
请你返回不同好路径的数目。
注意,一条路径和它反向的路径算作 同一 路径。比方说,0 -> 1与1 -> 0视为同一条路径。单个节点也视为一条合法路径。
示例 1:1
2
3
4
5
6输入:vals = [1,3,2,1,3], edges = [[0,1],[0,2],[2,3],[2,4]]
输出:6
解释:总共有 5 条单个节点的好路径。
还有 1 条好路径:1 -> 0 -> 2 -> 4 。
(反方向的路径 4 -> 2 -> 0 -> 1 视为跟 1 -> 0 -> 2 -> 4 一样的路径)
注意 0 -> 2 -> 3 不是一条好路径,因为 vals[2] > vals[0] 。
示例 2:1
2
3
4输入:vals = [1,1,2,2,3], edges = [[0,1],[1,2],[2,3],[2,4]]
输出:7
解释:总共有 5 条单个节点的好路径。
还有 2 条好路径:0 -> 1 和 2 -> 3 。
示例 3:1
2
3输入:vals = [1], edges = []
输出:1
解释:这棵树只有一个节点,所以只有一条好路径。
提示:
n == vals.length1 <= n <= 3 * 1040 <= vals[i] <= 105edges.length == n - 1edges[i].length == 20 <= ai, bi < nai != biedges表示一棵合法的树。
地址
https://leetcode.cn/contest/weekly-contest-312/problems/number-of-good-paths/
题意
排序 + 加并查集
思路
- 题目出的还可以,稍微有点思考难度。两点之间是否存在路径,最优先考虑到的是并查集,如果两个节点在同一个子集下,则两点之间一定存在路径,为了保证两点 $(a,b)$ 之间的路径上的节点值都满足小于等于 $vals[a],vals[b]$,则此时我们应当只把节点值小于 $vals[a]$ 的节点加入到并查集中,因此我们可以首先进行排序,按照每条边的节点值的最大值进行排序。
- 我们每次遍历当前节点值为 $x$ 时,我们将所有的边中的两个节点值都小于 $x$ 的边加入到并查集中,因为此时大于 $x$ 的边加入到并查集中无效,因为此时无法使用该条边。
- 对于对一个子集中且节点值相同的节点数目为 $cnt$,则此时可以构造题目要求的节点对的数目为 $\dfrac{cnt * (cnt + 1)}{2}$,因此我们将所有可能的节点对的数目相加即可。
- 复杂度分析:
- 时间复杂度:$O(m \log m + n \times \alpha(n))$,其中 $m$ 表示边的数目,$n$ 表示节点的数目。
- 空间复杂度:$O(n)$,$n$ 表示节点的数目。
代码
1 | |
#
欢迎关注和打赏,感谢支持!
- 关注我的博客: http://mikemeng.org/
- 关注我的知乎:https://www.zhihu.com/people/da-hua-niu
- 关注我的微信公众号: 公务程序猿
