
最后一题急了,冷静下来想想其实没那么麻烦
6132. 使数组中所有元素都等于零
给你一个非负整数数组 nums 。在一步操作中,你必须:
- 选出一个正整数 x ,x 需要小于或等于 nums 中 最小 的 非零 元素。
- nums 中的每个正整数都减去 x。
返回使 nums 中所有元素都等于_ _0 需要的 最少 操作数。
示例 1:
输入:nums = [1,5,0,3,5] 输出:3 解释: 第一步操作:选出 x = 1 ,之后 nums = [0,4,0,2,4] 。 第二步操作:选出 x = 2 ,之后 nums = [0,2,0,0,2] 。 第三步操作:选出 x = 2 ,之后 nums = [0,0,0,0,0] 。
示例 2:
输入:nums = [0] 输出:0 解释:nums 中的每个元素都已经是 0 ,所以不需要执行任何操作。
提示:
- 1 <= nums.length <= 100
- 0 <= nums[i] <= 100
思路:
找除0外不同数的个数
class Solution {public int minimumOperations(int[] nums) {// Arrays.sort(nums);Set<Integer> set = new HashSet<>();for (int x : nums) {if (x == 0) continue;set.add(x);}return set.size();}}
6133. 分组的最大数量
给你一个正整数数组 grades ,表示大学中一些学生的成绩。你打算将 所有 学生分为一些 有序 的非空分组,其中分组间的顺序满足以下全部条件:
- 第 i 个分组中的学生总成绩 小于 第 (i + 1) 个分组中的学生总成绩,对所有组均成立(除了最后一组)。
- 第 i 个分组中的学生总数 小于 第 (i + 1) 个分组中的学生总数,对所有组均成立(除了最后一组)。
返回可以形成的 最大 组数。
示例 1:
输入:grades = [10,6,12,7,3,5] 输出:3 解释:下面是形成 3 个分组的一种可行方法: - 第 1 个分组的学生成绩为 grades = [12] ,总成绩:12 ,学生数:1 - 第 2 个分组的学生成绩为 grades = [6,7] ,总成绩:6 + 7 = 13 ,学生数:2 - 第 3 个分组的学生成绩为 grades = [10,3,5] ,总成绩:10 + 3 + 5 = 18 ,学生数:3 可以证明无法形成超过 3 个分组。
示例 2:
输入:grades = [8,8] 输出:1 解释:只能形成 1 个分组,因为如果要形成 2 个分组的话,会导致每个分组中的学生数目相等。
提示:
- 1 <= grades.length <= 105
- 1 <= grades[i] <= 105
思路:
贪心,排序后从小到大,每组人数递增
class Solution {public int maximumGroups(int[] grades) {Arrays.sort(grades);int c = 1, s = 0;while (s + c <= grades.length) {s += c;c++;}return c - 1;}}
6134. 找到离给定两个节点最近的节点
- 通过的用户数2835
- 尝试过的用户数4068
- 用户总通过次数2935
- 用户总提交次数12895
- 题目难度Medium
给你一个 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 解释:从节点 0 到节点 2 的距离为 1 ,从节点 1 到节点 2 的距离为 1 。 两个距离的较大值为 1 。我们无法得到一个比 1 更小的较大值,所以我们返回节点 2 。
示例 2:
输入:edges = [1,2,-1], node1 = 0, node2 = 2 输出:2 解释:节点 0 到节点 2 的距离为 2 ,节点 2 到它自己的距离为 0 。 两个距离的较大值为 2 。我们无法得到一个比 2 更小的较大值,所以我们返回节点 2 。
提示:
- n == edges.length
- 2 <= n <= 105
- -1 <= edges[i] < n
- edges[i] != i
- 0 <= node1, node2 < n
思路:
比赛的时候用的bfs求两次最短路
其实每个点到其余所有点的路径都是唯一的,直接对着原数组遍历求就行
// 赛时代码class Solution {int N = 100010;int[] h = new int[N], e = new int[N], ne = new int[N];int[] d1 = new int[N], d2 = new int[N];int idx, n;public int closestMeetingNode(int[] edges, int node1, int node2) {n = edges.length;Arrays.fill(h, -1);for (int i = 0; i < n; i++) {if (edges[i] == -1) continue;add(i, edges[i]);}dijk(node1, d1);dijk(node2, d2);int max = 0x3f3f3f3f, node = n;for (int i = 0; i < n; i++) {if (d1[i] == 0x3f3f3f3f || d2[i] == 0x3f3f3f3f)continue;int v = Math.max(d1[i], d2[i]);if (v < max) {max = v;node = i;}}return max == 0x3f3f3f3f ? -1 : node;}void dijk(int s, int[] d) {Arrays.fill(d, 0x3f3f3f3f);Queue<Integer> q = new LinkedList<>();q.offer(s);d[s] = 0;int cnt = 0;while (!q.isEmpty()) {cnt++;int size = q.size();while (size-- > 0) {int u = q.poll();for (int i = h[u]; i != -1; i = ne[i]) {int j = e[i];if (d[j] > cnt) {d[j] = cnt;q.offer(j);}}}}}void add(int a, int b) {e[idx] = b;ne[idx] = h[a];h[a] = idx++;}}
class Solution {public int closestMeetingNode(int[] e, int node1, int node2) {int n = e.length;int[] d1 = new int[n], d2 = new int[n];Arrays.fill(d1, 0x3f3f3f3f);Arrays.fill(d2, 0x3f3f3f3f);d1[node1] = 0;for (int i = node1; i >= 0; i = e[i]) {int j = e[i];if (j == -1) break;if (d1[j] != 0x3f3f3f3f) break;d1[j] = d1[i] + 1;}d2[node2] = 0;for (int i = node2; i >= 0; i = e[i]) {int j = e[i];if (j == -1) break;if (d2[j] != 0x3f3f3f3f) break;d2[j] = d2[i] + 1;}int max = 0x3f3f3f3f, node = -1;for (int i = 0; i < n; i++) {int v = Math.max(d1[i], d2[i]);if (v < max) {max = v;node = i;}}return node;}}
6135. 图中的最长环
给你一个 n 个节点的 有向图 ,节点编号为 0 到 n - 1 ,其中每个节点 至多 有一条出边。
图用一个大小为 n 下标从 0 开始的数组 edges 表示,节点 i 到节点 edges[i] 之间有一条有向边。如果节点 i 没有出边,那么 edges[i] == -1 。
请你返回图中的 最长 环,如果没有任何环,请返回 -1 。
一个环指的是起点和终点是 同一个 节点的路径。
示例 1:
输入:edges = [3,3,4,2,3] 输出去:3 解释:图中的最长环是:2 -> 4 -> 3 -> 2 。 这个环的长度为 3 ,所以返回 3 。
示例 2:
输入:edges = [2,-1,3,1] 输出:-1 解释:图中没有任何环。
提示:
- n == edges.length
- 2 <= n <= 105
- -1 <= edges[i] < n
- edges[i] != i
思路:
遍历找环 + 时间计数器
class Solution {public int longestCycle(int[] e) {int n = e.length;int[] time = new int[n];int p = 1;int max = -1;for (int i = 0; i < n; i++) {if (time[i] > 0) continue;int j = i, start = p;while (j != -1 && time[j] == 0) {time[j] = p++;j = e[j];}if (j != -1 && time[j] >= start)max = Math.max(max, p - time[j]);}return max;}}// 优化空间写法class Solution {public int longestCycle(int[] e) {int p = 100000, base = 0xfffff;int max = -1;for (int i = 0; i < e.length; i++) {int j = i, c = 0;while (e[j] >= 0 && e[j] < e.length) {c++;int t = e[j];e[j] = hash(p, c);j = t;}if ((e[j] & base) == p) max = Math.max(max, c - (e[j] >> 20) + 1);p++;}return max;}int hash(int p, int c) {return (c << 20) + p;}}
