leetcode conttest 304
周赛的状态越来越不好,感觉第四题的状态越来越差,不过也感觉力扣好的题目越来越少了。套路题目太多了,感觉就刷一下周赛即可。
2357. 使数组中所有元素都等于零
题目
给你一个非负整数数组 nums
。在一步操作中,你必须:
- 选出一个正整数
x
,x
需要小于或等于nums
中 最小 的 非零 元素。 nums
中的每个正整数都减去x
。
返回使nums
中所有元素都等于0
需要的 最少 操作数。
示例 1:
输入:nums = [1,5,0,3,5] |
示例 2:
输入:nums = [0] |
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 100
地址
https://leetcode.cn/problems/make-array-zero-by-subtracting-equal-amounts/
题意
直接模拟
思路
- 首先我们可以直接模拟,将数组按照从小到大进行排序,然后按照从小到大的顺序依次取出元素 $x$,将所有的元素都减去 $x$,直到所有元素变为 $0$ 为止。
- 由于数组中所有的元素都不相同,因此每次模拟时,我们只能将其中一个元素变为 $0$,因此总共需要的次数即为数组中大于 $0$ 的不同元素的个数。
- 复杂度分析:
- 时间复杂度:$O(n)$,其中 $n$ 为数组元素的个数。
- 空间复杂度:$O(n)$,其中 $n$ 为数组元素的个数。
代码
- 直接模拟:
class Solution {
public:
int minimumOperations(vector<int>& nums) {
set<int> cnt;
sort(nums.begin(), nums.end());
int ans = 0;
int pos = 0;
while(nums.back() > 0) {
while(pos < nums.size() && nums[pos] == 0) {
pos++;
}
int x = nums[pos];
for(int i = pos; i < nums.size(); i++) {
nums[i] -= x;
}
ans++;
}
return ans;
}
}; - 数学:
class Solution {
public:
int minimumOperations(vector<int>& nums) {
int ans = 0;
unordered_set<int> cnt;
for (int i = 0; i < nums.size(); i++) {
if (nums[i] != 0) {
cnt.emplace(nums[i]);
}
}
return cnt.size();
}
};
2358. 分组的最大数量
题目
给你一个正整数数组 grades
,表示大学中一些学生的成绩。你打算将 所有 学生分为一些 有序 的非空分组,其中分组间的顺序满足以下全部条件:
- 第
i
个分组中的学生总成绩 小于 第 (i + 1
) 个分组中的学生总成绩,对所有组均成立(除了最后一组)。 - 第
i
个分组中的学生总数 小于 第 (i + 1
) 个分组中的学生总数,对所有组均成立(除了最后一组)。
返回可以形成的 最大 组数。
示例 1:
输入:grades = [10,6,12,7,3,5] |
示例 2:
输入:grades = [8,8] |
提示:
1 <= grades.length <= 105
1 <= grades[i] <= 105
地址
https://leetcode.cn/problems/maximum-number-of-groups-entering-a-competition
题意
贪心算法
思路
- 典型的贪心算法,若要是分组数目尽可能的大,则应该满足第一个分组尽可能的小,按照贪心规则可以知道第一个分组最小只能为数组中最小的元素。此时我们将第一个最小的元素去掉,再按照题目中要求的情况去模拟,找到第二个分组满足情况,当然经过仔细分析可以知道如下最大分组应该分布如下:
$$
(1,2,3,4,…,k)
$$
第一个分组中应有 $1$ 个元素,第二个分组中应有 $2$ 个元素,第三个分组中应有 $3$ 个元素。当然此时我们可以利用解一元二次方程即可。 - 复杂度分析:
- 时间复杂度:时间复杂度为 $O(1)$。
- 空间复杂度:$O(1)$。
代码
class Solution { |
2359. 找到离给定两个节点最近的节点
题目
给你一个 n
个节点的 有向图 ,节点编号为 0
到 n - 1
,每个节点 至多 有一条出边。
有向图用大小为 n
下标从 0
开始的数组 edges
表示,表示节点 i
有一条有向边指向 edges[i]
。如果节点 i
没有出边,那么 edges[i] == -1
。
同时给你两个节点 node1
和 node2
。
请你返回一个从 node1
和 node2
都能到达节点的编号,使节点 node1
和节点 node2
到这个节点的距离 较大值最小化。如果有多个答案,请返回 最小 的节点编号。如果答案不存在,返回 -1
。
注意 edges
可能包含环。
示例 1:
输入:edges = [2,2,3,-1], node1 = 0, node2 = 1 |
示例 2:
输入:edges = [1,2,-1], node1 = 0, node2 = 2 |
提示:
n == edges.length
2 <= n <= 105
-1 <= edges[i] < n
edges[i] != i
0 <= node1, node2 < n
地址
https://leetcode.cn/problems/find-closest-node-to-given-two-nodes
题意
BFS
思路
- 感觉是非常简单的
BFS
即可,通过BFS
分别求出所有节点到node1
与node2
的距离。然后依次遍历节点,找到二者之间共同可以访问的节点,并求出共同可以访问节点的距离之和的最小值即可,感觉没有多少难度,很直观的思路和解题方法。 - 复杂度分析:
- 时间复杂度:时间复杂度为 $O(n)$。
- 空间复杂度:空间复杂度为 $O(n)$。
代码
class Solution { |
2360. 图中的最长环
题目
给你一个 n
个节点的 有向图 ,节点编号为 0
到 n - 1
,其中每个节点 至多 有一条出边。
图用一个大小为 n
下标从 0
开始的数组 edges
表示,节点 i
到节点 edges[i]
之间有一条有向边。如果节点 i
没有出边,那么 edges[i] == -1
。
请你返回图中的 最长 环,如果没有任何环,请返回 -1
。
一个环指的是起点和终点是 同一个 节点的路径。
示例 1:
输入:edges = [3,3,4,2,3] |
示例 2:
输入:edges = [2,-1,3,1] |
提示:
n == edges.length
2 <= n <= 105
-1 <= edges[i] < n
edges[i] != i
地址
https://leetcode.cn/problems/longest-cycle-in-a-graph
题意
DFS
思路
- 经典题目,解法有很多种,经典的解法如下。
- 拓扑排序:首先我们可以利用拓扑排序将环以外的部分去掉,剩余未访问的节点均在环上,此时我们从环上任意一点开始访问求出环的最大深度即可,当然本题每条边的出度为 $1$,计算时更为简单,只需要循环即可。
DFS
标记: 参考题解:内向基环树找环 + 利用时间戳简单实现,感觉容易写错,当然可以老老实实的用拓扑排序方法,去掉非环上的所有节点。
- 复杂度分析:
- 时间复杂度:$O(n \log n)$,$n$ 表示数组的长度。
- 空间复杂度:$O(n)$,$n$ 表示数组的长度。
代码
class Solution { |
欢迎关注和打赏,感谢支持!
- 关注我的博客: http://mikemeng.org/
- 关注我的知乎:https://www.zhihu.com/people/da-hua-niu
- 关注我的微信公众号: 公务程序猿
扫描二维码,分享此文章