image.png
第一题看错题,还好稳住了

6160. 和有限的最长子序列

给你一个长度为 n 的整数数组 nums ,和一个长度为 m 的整数数组 queries 。
返回一个长度为 m 的数组 _answer ,其中 answer[i] _是 nums 中 元素之和小于等于 queries[i] 的 子序列最大 长度 。
子序列 是由一个数组删除某些元素(也可以不删除)但不改变剩余元素顺序得到的一个数组。

示例 1:
输入:nums = [4,5,2,1], queries = [3,10,21] 输出:[2,3,4] 解释:queries 对应的 answer 如下: - 子序列 [2,1] 的和小于或等于 3 。可以证明满足题目要求的子序列的最大长度是 2 ,所以 answer[0] = 2 。 - 子序列 [4,5,1] 的和小于或等于 10 。可以证明满足题目要求的子序列的最大长度是 3 ,所以 answer[1] = 3 。 - 子序列 [4,5,2,1] 的和小于或等于 21 。可以证明满足题目要求的子序列的最大长度是 4 ,所以 answer[2] = 4 。
示例 2:
输入:nums = [2,3,4,5], queries = [1] 输出:[0] 解释:空子序列是唯一一个满足元素和小于或等于 1 的子序列,所以 answer[0] = 0 。

提示:

  • n == nums.length
  • m == queries.length
  • 1 <= n, m <= 1000
  • 1 <= nums[i], queries[i] <= 106

思路:排序 + 二分
数据范围小,二分换成遍历

  1. class Solution {
  2. public int[] answerQueries(int[] nums, int[] q) {
  3. int n = nums.length, m = q.length;
  4. int[] res = new int[m];
  5. Arrays.sort(nums);
  6. int[] s = new int[n + 1];
  7. for (int i = 1; i <= n; i++)
  8. s[i] = s[i - 1] + nums[i - 1];
  9. for (int i = 0; i < m; i++) {
  10. int x = 0;
  11. for (int j = 1; j <= n; j++) {
  12. if (s[j] <= q[i])
  13. x = j;
  14. }
  15. res[i] = x;
  16. }
  17. return res;
  18. }
  19. }

6161. 从字符串中移除星号

给你一个包含若干星号 * 的字符串 s 。
在一步操作中,你可以:

  • 选中 s 中的一个星号。
  • 移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。

返回移除 所有 星号之后的字符串
注意:

  • 生成的输入保证总是可以执行题面中描述的操作。
  • 可以证明结果字符串是唯一的。

示例 1:
输入:s = “leetcod*e” 输出:“lecoe” 解释:从左到右执行移除操作: - 距离第 1 个星号最近的字符是 “lee_t_code” 中的 ‘t’ ,s 变为 “leecode” 。 - 距离第 2 个星号最近的字符是 “leecode” 中的 ‘e’ ,s 变为 “lecode” 。 - 距离第 3 个星号最近的字符是 “lecode” 中的 ‘d’ ,s 变为 “lecoe” 。 不存在其他星号,返回 “lecoe” 。
示例 2:
输入:s = “erase**
输出:“” 解释:整个字符串都会被移除,所以返回空字符串。

提示:

  • 1 <= s.length <= 105
  • s 由小写英文字母和星号 * 组成
  • s 可以执行上述操作

思路:双端队列

  1. class Solution {
  2. public String removeStars(String s) {
  3. Deque<Character> q = new LinkedList<>();
  4. for (int i = 0; i < s.length(); i++) {
  5. if (s.charAt(i) == '*') {
  6. q.pollLast();
  7. } else {
  8. q.offer(s.charAt(i));
  9. }
  10. }
  11. StringBuilder sb = new StringBuilder();
  12. while (!q.isEmpty())
  13. sb.append(q.poll());
  14. return sb.toString();
  15. }
  16. }

6162. 收集垃圾的最少总时间

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

  • 通过的用户数4065
  • 尝试过的用户数4116
  • 用户总通过次数4136
  • 用户总提交次数4636
  • 题目难度Medium

给你一个下标从 0 开始的字符串数组 garbage ,其中 garbage[i] 表示第 i 个房子的垃圾集合。garbage[i] 只包含字符 ‘M’ ,’P’ 和 ‘G’ ,但可能包含多个相同字符,每个字符分别表示一单位的金属、纸和玻璃。垃圾车收拾 单位的任何一种垃圾都需要花费 1 分钟。
同时给你一个下标从 0 开始的整数数组 travel ,其中 travel[i] 是垃圾车从房子 i 行驶到房子 i + 1 需要的分钟数。
城市里总共有三辆垃圾车,分别收拾三种垃圾。每辆垃圾车都从房子 0 出发,按顺序 到达每一栋房子。但它们 不是必须 到达所有的房子。
任何时刻只有 一辆 垃圾车处在使用状态。当一辆垃圾车在行驶或者收拾垃圾的时候,另外两辆车 不能 做任何事情。
请你返回收拾完所有垃圾需要花费的 最少 总分钟数。

示例 1:
输入:garbage = [“G”,”P”,”GP”,”GG”], travel = [2,4,3] 输出:21 解释: 收拾纸的垃圾车: 1. 从房子 0 行驶到房子 1 2. 收拾房子 1 的纸垃圾 3. 从房子 1 行驶到房子 2 4. 收拾房子 2 的纸垃圾 收拾纸的垃圾车总共花费 8 分钟收拾完所有的纸垃圾。 收拾玻璃的垃圾车: 1. 收拾房子 0 的玻璃垃圾 2. 从房子 0 行驶到房子 1 3. 从房子 1 行驶到房子 2 4. 收拾房子 2 的玻璃垃圾 5. 从房子 2 行驶到房子 3 6. 收拾房子 3 的玻璃垃圾 收拾玻璃的垃圾车总共花费 13 分钟收拾完所有的玻璃垃圾。 由于没有金属垃圾,收拾金属的垃圾车不需要花费任何时间。 所以总共花费 8 + 13 = 21 分钟收拾完所有垃圾。
示例 2:
输入:garbage = [“MMM”,”PGM”,”GP”], travel = [3,10] 输出:37 解释: 收拾金属的垃圾车花费 7 分钟收拾完所有的金属垃圾。 收拾纸的垃圾车花费 15 分钟收拾完所有的纸垃圾。 收拾玻璃的垃圾车花费 15 分钟收拾完所有的玻璃垃圾。 总共花费 7 + 15 + 15 = 37 分钟收拾完所有的垃圾。

提示:

  • 2 <= garbage.length <= 105
  • garbage[i] 只包含字母 ‘M’ ,’P’ 和 ‘G’ 。
  • 1 <= garbage[i].length <= 10
  • travel.length == garbage.length - 1
  • 1 <= travel[i] <= 100

思路:模拟

  1. class Solution {
  2. public int garbageCollection(String[] g, int[] t) {
  3. int n = g.length;
  4. int[][] cnt = new int[n][3];
  5. for (int i = 0; i < n; i++) {
  6. for (int j = 0; j < g[i].length(); j++) {
  7. if (g[i].charAt(j) == 'M')
  8. cnt[i][0]++;
  9. else if (g[i].charAt(j) == 'P')
  10. cnt[i][1]++;
  11. else cnt[i][2]++;
  12. }
  13. }
  14. int res = 0;
  15. int p = 0;
  16. for (int i = 0; i < n; i++) {
  17. if (i > 0) p += t[i - 1];
  18. if (cnt[i][0] != 0) {
  19. res += cnt[i][0] + p;
  20. p = 0;
  21. }
  22. }
  23. p = 0;
  24. for (int i = 0; i < n; i++) {
  25. if (i > 0) p += t[i - 1];
  26. if (cnt[i][1] != 0) {
  27. res += cnt[i][1] + p;
  28. p = 0;
  29. }
  30. }
  31. p = 0;
  32. for (int i = 0; i < n; i++) {
  33. if (i > 0) p += t[i - 1];
  34. if (cnt[i][2] != 0) {
  35. res += cnt[i][2] + p;
  36. p = 0;
  37. }
  38. }
  39. return res;
  40. }
  41. }

6163. 给定条件下构造矩阵

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

  • 通过的用户数1310
  • 尝试过的用户数1676
  • 用户总通过次数1451
  • 用户总提交次数3033
  • 题目难度Hard

给你一个 整数 k ,同时给你:

  • 一个大小为 n 的二维整数数组 rowConditions ,其中 rowConditions[i] = [abovei, belowi] 和
  • 一个大小为 m 的二维整数数组 colConditions ,其中 colConditions[i] = [lefti, righti] 。

两个数组里的整数都是 1 到 k 之间的数字。
你需要构造一个 k x k 的矩阵,1 到 k 每个数字需要 恰好出现一次 。剩余的数字都是 0 。
矩阵还需要满足以下条件:

  • 对于所有 0 到 n - 1 之间的下标 i ,数字 abovei 所在的 必须在数字 belowi 所在行的上面。
  • 对于所有 0 到 m - 1 之间的下标 i ,数字 lefti 所在的 必须在数字 righti 所在列的左边。

返回满足上述要求的 任意 矩阵。如果不存在答案,返回一个空的矩阵。

示例 1:
image.png
输入:k = 3, rowConditions = [[1,2],[3,2]], colConditions = [[2,1],[3,2]] 输出:[[3,0,0],[0,0,1],[0,2,0]] 解释:上图为一个符合所有条件的矩阵。 行要求如下: - 数字 1 在第 1 行,数字 2 在第 2 行,1 在 2 的上面。 - 数字 3 在第 0 行,数字 2 在第 2 行,3 在 2 的上面。 列要求如下: - 数字 2 在第 1 列,数字 1 在第 2 列,2 在 1 的左边。 - 数字 3 在第 0 列,数字 2 在第 1 列,3 在 2 的左边。 注意,可能有多种正确的答案。
示例 2:
输入:k = 3, rowConditions = [[1,2],[2,3],[3,1],[2,3]], colConditions = [[2,1]] 输出:[] 解释:由前两个条件可以得到 3 在 1 的下面,但第三个条件是 3 在 1 的上面。 没有符合条件的矩阵存在,所以我们返回空矩阵。

提示:

  • 2 <= k <= 400
  • 1 <= rowConditions.length, colConditions.length <= 104
  • rowConditions[i].length == colConditions[i].length == 2
  • 1 <= abovei, belowi, lefti, righti <= k
  • abovei != belowi
  • lefti != righti

思路:拓扑排序

  1. class Solution {
  2. int N = 10010;
  3. int[] h = new int[N], e = new int[N], ne = new int[N], in = new int[N];
  4. int idx;
  5. List<Integer> row = new ArrayList<>();
  6. List<Integer> col = new ArrayList<>();
  7. int k;
  8. public int[][] buildMatrix(int k, int[][] r, int[][] c) {
  9. this.k = k;
  10. if (!topo(r, 0) || !topo(c, 1))
  11. return new int[0][0];
  12. Map<Integer, Integer> m1 = new HashMap<>();
  13. Map<Integer, Integer> m2 = new HashMap<>();
  14. for (int i = 0; i < k; i++) {
  15. int x = row.get(i);
  16. m1.put(x, i);
  17. }
  18. for (int i = 0; i < k; i++) {
  19. int x = col.get(i);
  20. m2.put(x, i);
  21. }
  22. // System.out.println(row);
  23. // System.out.println(col);
  24. int[][] res = new int[k][k];
  25. for (int i = 1; i <= k; i++) {
  26. int x = m1.get(i), y = m2.get(i);
  27. res[x][y] = i;
  28. }
  29. return res;
  30. }
  31. boolean topo(int[][] r, int op) {
  32. Arrays.fill(h, -1);
  33. idx = 0;
  34. Arrays.fill(in, 0);
  35. for (int[] p : r) {
  36. int a = p[0], b = p[1];
  37. add(a, b);
  38. }
  39. List<Integer> a = new ArrayList<>();
  40. Queue<Integer> q = new LinkedList<>();
  41. for (int i = 1; i <= k; i++) {
  42. if (in[i] == 0) {
  43. q.offer(i);
  44. a.add(i);
  45. }
  46. }
  47. while (!q.isEmpty()) {
  48. int u = q.poll();
  49. for (int i = h[u]; i != -1; i = ne[i]) {
  50. int j = e[i];
  51. in[j]--;
  52. if (in[j] == 0) {
  53. q.offer(j);
  54. a.add(j);
  55. }
  56. }
  57. }
  58. if (a.size() != k) return false;
  59. if (op == 0) row = new ArrayList<>(a);
  60. else col = new ArrayList<>(a);
  61. return true;
  62. }
  63. void add(int a, int b) {
  64. e[idx] = b;
  65. ne[idx] = h[a];
  66. in[b]++;
  67. h[a] = idx++;
  68. }
  69. }