去北校区忙搬实验室了,没有参加,有点遗憾

6188. 按身高排序

给你一个字符串数组 names ,和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。
对于每个下标 i,names[i] 和 heights[i] 表示第 i 个人的名字和身高。
请按身高 降序 顺序返回对应的名字数组 names 。

示例 1:
输入:names = [“Mary”,”John”,”Emma”], heights = [180,165,170] 输出:[“Mary”,”Emma”,”John”] 解释:Mary 最高,接着是 Emma 和 John 。
示例 2:
输入:names = [“Alice”,”Bob”,”Bob”], heights = [155,185,150] 输出:[“Bob”,”Alice”,”Bob”] 解释:第一个 Bob 最高,然后是 Alice 和第二个 Bob 。

提示:

  • n == names.length == heights.length
  • 1 <= n <= 103
  • 1 <= names[i].length <= 20
  • 1 <= heights[i] <= 105
  • names[i] 由大小写英文字母组成
  • heights 中的所有值互不相同

思路:
排个序即可

  1. class Solution {
  2. public String[] sortPeople(String[] names, int[] heights) {
  3. int n = names.length;
  4. Pair[] p = new Pair[n];
  5. for (int i = 0; i < n; i++) {
  6. p[i] = new Pair(names[i], heights[i]);
  7. }
  8. Arrays.sort(p, (o1, o2) -> (o2.height - o1.height));
  9. for (int i = 0; i < n; i++)
  10. names[i] = p[i].name;
  11. return names;
  12. }
  13. class Pair {
  14. String name;
  15. int height;
  16. Pair(String name, int height) {
  17. this.name = name;
  18. this.height = height;
  19. }
  20. }
  21. }

6189. 按位与最大的最长子数组

给你一个长度为 n 的整数数组 nums 。
考虑 nums 中进行 按位与(bitwise AND)运算得到的值 最大非空 子数组。

  • 换句话说,令 k 是 nums 任意 子数组执行按位与运算所能得到的最大值。那么,只需要考虑那些执行一次按位与运算后等于 k 的子数组。

返回满足要求的 最长 子数组的长度。
数组的按位与就是对数组中的所有数字进行按位与运算。
子数组 是数组中的一个连续元素序列。

示例 1:
输入:nums = [1,2,3,3,2,2] 输出:2 解释: 子数组按位与运算的最大值是 3 。 能得到此结果的最长子数组是 [3,3],所以返回 2 。
示例 2:
输入:nums = [1,2,3,4] 输出:1 解释: 子数组按位与运算的最大值是 4 。 能得到此结果的最长子数组是 [4],所以返回 1 。

提示:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 106

思路:
即找数组最大值的连续出现次数的最大值

  1. class Solution {
  2. public int longestSubarray(int[] nums) {
  3. int max = 0;
  4. for (int x : nums) max = Math.max(max, x);
  5. int len = 0;
  6. for (int i = 0; i < nums.length; i++) {
  7. if (nums[i] == max) {
  8. int j = i;
  9. while (j < nums.length && nums[j] == max)
  10. j++;
  11. len = Math.max(j - i, len);
  12. i = j - 1;
  13. }
  14. }
  15. return len;
  16. }
  17. }

6190. 找到所有好下标

给你一个大小为 n 下标从 0 开始的整数数组 nums 和一个正整数 k 。
对于 k <= i < n - k 之间的一个下标 i ,如果它满足以下条件,我们就称它为一个 下标:

  • 下标 i 之前 的 k 个元素是 非递增的
  • 下标 i 之后 的 k 个元素是 非递减的

升序 返回所有好下标。

示例 1:
输入: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:
输入:nums = [2,1,1,2], k = 2 输出:[] 解释:数组中没有好下标。

提示:

  • n == nums.length
  • 3 <= n <= 105
  • 1 <= nums[i] <= 106
  • 1 <= k <= n / 2

思路:
线性DP

  1. class Solution {
  2. public List<Integer> goodIndices(int[] nums, int k) {
  3. int n = nums.length;
  4. int[] left = new int[n], right = new int[n];
  5. left[0] = 1;
  6. for (int i = 1; i < n; i++) {
  7. if (nums[i] <= nums[i - 1])
  8. left[i] = left[i - 1] + 1;
  9. else left[i] = 1;
  10. }
  11. right[n - 1] = 1;
  12. for (int i = n - 2; i >= 0; i--) {
  13. if (nums[i] <= nums[i + 1])
  14. right[i] = right[i + 1] + 1;
  15. else right[i] = 1;
  16. }
  17. List<Integer> res = new ArrayList<>();
  18. for (int i = 1; i < n - 1; i++) {
  19. if (left[i - 1] >= k && right[i + 1] >= k)
  20. res.add(i);
  21. }
  22. return res;
  23. }
  24. }

6191. 好路径的数目

显示英文描述
我的提交返回竞赛

  • 通过的用户数280
  • 尝试过的用户数1024
  • 用户总通过次数345
  • 用户总提交次数2602
  • 题目难度Hard

给你一棵 n 个节点的树(连通无向无环的图),节点编号从 0 到 n - 1 且恰好有 n - 1 条边。
给你一个长度为 n 下标从 0 开始的整数数组 vals ,分别表示每个节点的值。同时给你一个二维整数数组 edges ,其中 edges[i] = [ai, bi] 表示节点 ai 和 bi 之间有一条 无向 边。
一条 好路径 需要满足以下条件:

  1. 开始节点和结束节点的值 相同
  2. 开始节点和结束节点中间的所有节点值都 小于等于 开始节点的值(也就是说开始节点的值应该是路径上所有节点的最大值)。

请你返回不同好路径的数目。
注意,一条路径和它反向的路径算作 同一 路径。比方说, 0 -> 1 与 1 -> 0 视为同一条路径。单个节点也视为一条合法路径。

示例 1:
image.png
输入: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:
image.png
输入:vals = [1,1,2,2,3], edges = [[0,1],[1,2],[2,3],[2,4]] 输出:7 解释:总共有 5 条单个节点的好路径。 还有 2 条好路径:0 -> 1 和 2 -> 3 。
示例 3:
image.png
输入:vals = [1], edges = [] 输出:1 解释:这棵树只有一个节点,所以只有一条好路径。

提示:

  • n == vals.length
  • 1 <= n <= 3 * 104
  • 0 <= vals[i] <= 105
  • edges.length == n - 1
  • edges[i].length == 2
  • 0 <= ai, bi < n
  • ai != bi
  • edges 表示一棵合法的树。

思路:
排序 + 并查集

  1. class Solution {
  2. public int numberOfGoodPaths(int[] vals, int[][] edges) {
  3. Arrays.sort(edges, (o1, o2) -> {
  4. int a = Math.max(vals[o1[0]], vals[o1[1]]), b = Math.max(vals[o2[0]], vals[o2[1]]);
  5. return a - b;
  6. });
  7. int n = vals.length;
  8. UnionFind uf = new UnionFind(n);
  9. uf.init(vals);
  10. int res = n;
  11. for (int[] e : edges) {
  12. int a = e[0], b = e[1];
  13. int v = Math.max(vals[a], vals[b]);
  14. res += uf.merge(a, b);
  15. }
  16. return res;
  17. }
  18. }
  19. class UnionFind {
  20. int[] fa;
  21. int[] size;
  22. int[] max;
  23. int n;
  24. UnionFind(int n) {
  25. this.n = n;
  26. fa = new int[n];
  27. for (int i = 0; i < n; i++)
  28. fa[i] = i;
  29. max = new int[n];
  30. size = new int[n];
  31. }
  32. void init(int[] a) {
  33. for (int i = 0; i < a.length; i++) {
  34. max[i] = a[i];
  35. size[i] = 1;
  36. }
  37. }
  38. int merge(int a, int b) {
  39. int pa = find(a), pb = find(b);
  40. int res = max[pa] == max[pb] ? size[pa] * size[pb] : 0;
  41. fa[pa] = pb;
  42. if (max[pa] == max[pb]) {
  43. size[pb] += size[pa];
  44. } else if (max[pa] > max[pb]) {
  45. size[pb] = size[pa];
  46. max[pb] = max[pa];
  47. }
  48. return res;
  49. }
  50. int find(int x) {
  51. return fa[x] == x ? x : (fa[x] = find(fa[x]));
  52. }
  53. }