image.png
又是3题的夜晚,注定睡不好觉

6051. 统计是给定字符串前缀的字符串数目

给你一个字符串数组 words 和一个字符串 s ,其中 words[i] 和 s 只包含 小写英文字母
请你返回 words 中是字符串 s 前缀 字符串数目
一个字符串的 前缀 是出现在字符串开头的子字符串。子字符串 是一个字符串中的连续一段字符序列。

示例 1:
输入:words = [“a”,”b”,”c”,”ab”,”bc”,”abc”], s = “abc” 输出:3 解释: words 中是 s = “abc” 前缀的字符串为: “a” ,”ab” 和 “abc” 。 所以 words 中是字符串 s 前缀的字符串数目为 3 。
示例 2:
输入:words = [“a”,”a”], s = “aa” 输出:2 解释: 两个字符串都是 s 的前缀。 注意,相同的字符串可能在 words 中出现多次,它们应该被计数多次。

提示:

  • 1 <= words.length <= 1000
  • 1 <= words[i].length, s.length <= 10
  • words[i] 和 s 包含小写英文字母。

思路:
API使用
时间复杂度: O(nm), n指words的长度,m指字符串长度

  1. class Solution {
  2. public int countPrefixes(String[] words, String s) {
  3. int cnt = 0;
  4. for (String w : words) {
  5. if (s.startsWith(w))
  6. cnt++;
  7. }
  8. return cnt;
  9. }
  10. }

6052. 最小平均差

给你一个下标从 0 开始长度为 n 的整数数组 nums 。
下标 i 处的 平均差 指的是 nums 中 i + 1 个元素平均值和 n - i - 1 个元素平均值的 绝对差 。两个平均值都需要 向下取整 到最近的整数。
请你返回产生 最小平均差 的下标。如果有多个下标最小平均差相等,请你返回 最小 的一个下标。
注意:

  • 两个数的 绝对差 是两者差的绝对值。
  • n 个元素的平均值是 n 个元素之 除以(整数除法) n 。
  • 0 个元素的平均值视为 0 。

示例 1:
输入:nums = [2,5,3,9,5,3]
输出:3
解释:
- 下标 0 处的平均差为:|2 / 1 - (5 + 3 + 9 + 5 + 3) / 5| = |2 / 1 - 25 / 5| = |2 - 5| = 3 。
- 下标 1 处的平均差为:|(2 + 5) / 2 - (3 + 9 + 5 + 3) / 4| = |7 / 2 - 20 / 4| = |3 - 5| = 2 。
- 下标 2 处的平均差为:|(2 + 5 + 3) / 3 - (9 + 5 + 3) / 3| = |10 / 3 - 17 / 3| = |3 - 5| = 2 。
- 下标 3 处的平均差为:|(2 + 5 + 3 + 9) / 4 - (5 + 3) / 2| = |19 / 4 - 8 / 2| = |4 - 4| = 0 。
- 下标 4 处的平均差为:|(2 + 5 + 3 + 9 + 5) / 5 - 3 / 1| = |24 / 5 - 3 / 1| = |4 - 3| = 1 。
- 下标 5 处的平均差为:|(2 + 5 + 3 + 9 + 5 + 3) / 6 - 0| = |27 / 6 - 0| = |4 - 0| = 4 。
下标 3 处的平均差为最小平均差,所以返回 3 。
示例 2:
输入:nums = [0]
输出:0
解释: 唯一的下标是 0 ,所以我们返回 0 。 下标 0 处的平均差为:|0 / 1 - 0| = |0 - 0| = 0 。

提示:

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

思路:
前缀和
时间复杂度:O(n)
空间复杂度:O(n)

  1. class Solution {
  2. public int minimumAverageDifference(int[] nums) {
  3. int n = nums.length;
  4. long[] s = new long[n];
  5. s[0] = nums[0];
  6. for (int i = 1; i < n; i++)
  7. s[i] = s[i - 1] + nums[i];
  8. int min = 0x3f3f3f3f, idx = -1;
  9. for (int i = 0; i < n; i++) {
  10. long pre = s[i] / (i + 1);
  11. long last = i == n - 1 ? 0 : (s[n - 1] - s[i]) / (n - i - 1);
  12. int minus = (int)(Math.abs(pre - last));
  13. if (minus < min) {
  14. min = minus;
  15. idx = i;
  16. }
  17. }
  18. return idx;
  19. }
  20. }

6053. 统计网格图中没有被保卫的格子数

给你两个整数 m 和 n 表示一个下标从 0 开始的 m x n 网格图。同时给你两个二维整数数组 guards 和 walls ,其中 guards[i] = [rowi, coli] 且 walls[j] = [rowj, colj] ,分别表示第 i 个警卫和第 j 座墙所在的位置。
一个警卫能看到 4 个坐标轴方向(即东、南、西、北)的 所有 格子,除非他们被一座墙或者另外一个警卫 挡住 了视线。如果一个格子能被 至少 一个警卫看到,那么我们说这个格子被 保卫 了。
请你返回空格子中,有多少个格子是 没被保卫 的。

示例 1:
image.png
输入:m = 4, n = 6, guards = [[0,0],[1,1],[2,3]], walls = [[0,1],[2,2],[1,4]] 输出:7 解释:上图中,被保卫和没有被保卫的格子分别用红色和绿色表示。 总共有 7 个没有被保卫的格子,所以我们返回 7 。
示例 2:
image.png
输入:m = 3, n = 3, guards = [[1,1]], walls = [[0,1],[1,0],[2,1],[1,2]] 输出:4 解释:上图中,没有被保卫的格子用绿色表示。 总共有 4 个没有被保卫的格子,所以我们返回 4 。

提示:

  • 1 <= m, n <= 105
  • 2 <= m * n <= 105
  • 1 <= guards.length, walls.length <= 5 * 104
  • 2 <= guards.length + walls.length <= m * n
  • guards[i].length == walls[j].length == 2
  • 0 <= rowi, rowj < m
  • 0 <= coli, colj < n
  • guards 和 walls 中所有位置 互不相同

思路:
四个方向分别考虑
时间复杂度: O(nm)
空间复杂度: O(nm)

  1. class Solution {
  2. public int countUnguarded(int n, int m, int[][] guards, int[][] walls) {
  3. int[][] st = new int[n][m];
  4. for (int[] g : guards) {
  5. st[g[0]][g[1]] = 2;
  6. }
  7. for (int[] w : walls) {
  8. st[w[0]][w[1]] = -1;
  9. }
  10. for (int i = 0; i < n; i++) {
  11. boolean flag = false;
  12. for (int j = 0; j < m; j++) {
  13. if (st[i][j] == 2) {
  14. flag = true;
  15. continue;
  16. }
  17. if (st[i][j] == -1) {
  18. flag = false;
  19. continue;
  20. }
  21. if (flag)
  22. st[i][j] = 1;
  23. }
  24. flag = false;
  25. for (int j = m - 1; j >= 0; j--) {
  26. if (st[i][j] == 2) {
  27. flag = true;
  28. continue;
  29. }
  30. if (st[i][j] == -1) {
  31. flag = false;
  32. continue;
  33. }
  34. if (flag)
  35. st[i][j] = 1;
  36. }
  37. }
  38. for (int j = 0; j < m; j++) {
  39. boolean flag = false;
  40. for (int i = 0; i < n; i++) {
  41. if (st[i][j] == 2) {
  42. flag = true;
  43. continue;
  44. }
  45. if (st[i][j] == -1) {
  46. flag = false;
  47. continue;
  48. }
  49. if (flag)
  50. st[i][j] = 1;
  51. }
  52. flag = false;
  53. for (int i = n - 1; i >= 0; i--) {
  54. if (st[i][j] == 2) {
  55. flag = true;
  56. continue;
  57. }
  58. if (st[i][j] == -1) {
  59. flag = false;
  60. continue;
  61. }
  62. if (flag)
  63. st[i][j] = 1;
  64. }
  65. }
  66. int cnt = 0;
  67. for (int i = 0; i < n; i++) {
  68. for (int j = 0; j < m; j++) {
  69. if (st[i][j] == 0)
  70. cnt++;
  71. }
  72. }
  73. // System.out.println(Arrays.deepToString(st));
  74. return cnt;
  75. }
  76. }

6054. 逃离火灾

给你一个下标从 0 开始大小为 m x n 的二维整数数组 grid ,它表示一个网格图。每个格子为下面 3 个值之一:

  • 0 表示草地。
  • 1 表示着火的格子。
  • 2 表示一座墙,你跟火都不能通过这个格子。

一开始你在最左上角的格子 (0, 0) ,你想要到达最右下角的安全屋格子 (m - 1, n - 1) 。每一分钟,你可以移动到 相邻 的草地格子。每次你移动 之后 ,着火的格子会扩散到所有不是墙的 相邻 格子。
请你返回你在初始位置可以停留的 最多 分钟数,且停留完这段时间后你还能安全到达安全屋。如果无法实现,请你返回 -1 。如果不管你在初始位置停留多久,你 总是 能到达安全屋,请你返回 109 。
注意,如果你到达安全屋后,火马上到了安全屋,这视为你能够安全到达安全屋。
如果两个格子有共同边,那么它们为 相邻 格子。

示例 1:
image.png
输入:grid = [[0,2,0,0,0,0,0],[0,0,0,2,2,1,0],[0,2,0,0,1,2,0],[0,0,2,2,2,0,2],[0,0,0,0,0,0,0]] 输出:3 解释:上图展示了你在初始位置停留 3 分钟后的情形。 你仍然可以安全到达安全屋。 停留超过 3 分钟会让你无法安全到达安全屋。
示例 2:
image.png
输入:grid = [[0,0,0,0],[0,1,2,0],[0,2,0,0]] 输出:-1 解释:上图展示了你马上开始朝安全屋移动的情形。 火会蔓延到你可以移动的所有格子,所以无法安全到达安全屋。 所以返回 -1 。
示例 3:
image.png
输入:grid = [[0,0,0],[2,2,0],[1,2,0]] 输出:1000000000 解释:上图展示了初始网格图。 注意,由于火被墙围了起来,所以无论如何你都能安全到达安全屋。 所以返回 109 。

提示:

  • m == grid.length
  • n == grid[i].length
  • 2 <= m, n <= 300
  • 4 <= m n <= 2 104
  • grid[i][j] 是 0 ,1 或者 2 。
  • grid[0][0] == grid[m - 1][n - 1] == 0

思路:
bfs + 二分
时间复杂度:O(nmlog(nm))
空间复杂度:O(nm)

  1. class Solution {
  2. int n, m;
  3. boolean[][] st;
  4. int[][] p, f;
  5. int inf = 1000000000;
  6. public int maximumMinutes(int[][] grid) {
  7. n = grid.length;
  8. m = grid[0].length;
  9. st = new boolean[n][m];
  10. p = new int[n][m];
  11. f = new int[n][m];
  12. for (int i = 0; i < n; i++) {
  13. Arrays.fill(f[i], -1);
  14. Arrays.fill(p[i], -1);
  15. }
  16. bfs(grid);
  17. if (!check(0, grid))
  18. return -1;
  19. if (check(inf, grid))
  20. return inf;
  21. int l = 0, r = inf;
  22. while (l < r) {
  23. int mid = l + r + 1 >> 1;
  24. if (check(mid, grid))
  25. l = mid;
  26. else
  27. r = mid - 1;
  28. }
  29. return l;
  30. }
  31. boolean check(int w, int[][] grid) {
  32. Queue<int[]> q = new LinkedList<>();
  33. for (int i = 0; i < n; i++) {
  34. Arrays.fill(st[i], false);
  35. }
  36. q.offer(new int[]{0, 0});
  37. st[0][0] = true;
  38. while (!q.isEmpty()) {
  39. int[] cur = q.poll();
  40. int x = cur[0], y = cur[1];
  41. for (int i = 0; i < 4; i++) {
  42. int a = x + dx[i], b = y + dy[i];
  43. if (a < 0 || a >= n || b < 0 || b >= m || grid[a][b] == 2 || st[a][b])
  44. continue;
  45. if (a == n - 1 && b == m - 1 && (f[a][b] == -1 || p[a][b] + w <= f[a][b]))
  46. return true;
  47. if (f[a][b] == -1 || p[a][b] + w < f[a][b]) {
  48. st[a][b] = true;
  49. q.offer(new int[]{a, b});
  50. }
  51. }
  52. }
  53. return false;
  54. }
  55. int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
  56. void bfs(int[][] grid) {
  57. Queue<int[]> q = new LinkedList<>();
  58. q.offer(new int[]{0, 0});
  59. st[0][0] = true;
  60. p[0][0] = 0;
  61. int cnt = 0;
  62. while (!q.isEmpty()) {
  63. cnt++;
  64. int size = q.size();
  65. while (size -- > 0) {
  66. int[] cur = q.poll();
  67. int x = cur[0], y = cur[1];
  68. for (int i = 0; i < 4; i++) {
  69. int a = x + dx[i], b = y + dy[i];
  70. if (a < 0 || a >= n || b < 0 || b >= m || grid[a][b] == 2 || st[a][b])
  71. continue;
  72. st[a][b] = true;
  73. p[a][b] = cnt;
  74. q.offer(new int[]{a, b});
  75. }
  76. }
  77. }
  78. for (int i = 0; i < n; i++) {
  79. Arrays.fill(st[i], false);
  80. for (int j = 0; j < m; j++) {
  81. if (grid[i][j] == 1) {
  82. q.offer(new int[]{i, j});
  83. st[i][j] = true;
  84. f[i][j] = 0;
  85. }
  86. }
  87. }
  88. cnt = 0;
  89. while (!q.isEmpty()) {
  90. cnt++;
  91. int size = q.size();
  92. while (size -- > 0) {
  93. int[] cur = q.poll();
  94. int x = cur[0], y = cur[1];
  95. for (int i = 0; i < 4; i++) {
  96. int a = x + dx[i], b = y + dy[i];
  97. if (a < 0 || a >= n || b < 0 || b >= m || grid[a][b] == 2 || st[a][b])
  98. continue;
  99. st[a][b] = true;
  100. f[a][b] = cnt;
  101. q.offer(new int[]{a, b});
  102. }
  103. }
  104. }
  105. }
  106. }