image.png
我愿称之为离散化场!3和4都是差分 + 离散化,只不过一个1维,一个2维罢了,T4还比T3简单。。。

6041. 多个数组求交集

给你一个二维整数数组 nums ,其中 nums[i] 是由 不同 正整数组成的一个非空数组,按 升序排列 返回一个数组,数组中的每个元素在 nums 所有数组 中都出现过。

示例 1:
输入:nums = [[3,1,2,4,5],[1,2,3,4],[3,4,5,6]] 输出:[3,4] 解释: nums[0] = [3,1,2,4,5],nums[1] = [1,2,3,4],nums[2] = [3,4,5,6],在 nums 中每个数组中都出现的数字是 3 和 4 ,所以返回 [3,4] 。
示例 2:
输入:nums = [[1,2,3],[4,5,6]] 输出:[] 解释: 不存在同时出现在 nums[0] 和 nums[1] 的整数,所以返回一个空列表 [] 。

提示:

  • 1 <= nums.length <= 1000
  • 1 <= sum(nums[i].length) <= 1000
  • 1 <= nums[i][j] <= 1000
  • nums[i] 中的所有值 互不相同

思路:
暴力模拟即可
时间复杂度:O(n2)

  1. class Solution {
  2. public List<Integer> intersection(int[][] nums) {
  3. int n = nums.length, m = nums[0].length;
  4. List<Integer> res = new ArrayList<>();
  5. for (int x : nums[0]) {
  6. int cnt = 1;
  7. for (int i = 1; i < n; i++)
  8. for (int v : nums[i]) {
  9. if (v == x) {
  10. cnt++;
  11. break;
  12. }
  13. }
  14. if (cnt == n)
  15. res.add(x);
  16. }
  17. Collections.sort(res);
  18. return res;
  19. }
  20. }
  21. // 灵活调用API
  22. //boolean retainAll(Collection<?> c)
  23. class Solution {
  24. public List<Integer> intersection(int[][] nums) {
  25. Set<Integer> set = new HashSet<>();
  26. List<Integer> res = new ArrayList<>();
  27. for (int x : nums[0])
  28. set.add(x);
  29. for (int[] p : nums) {
  30. Set<Integer> t = new HashSet<>();
  31. for (int x : p) {
  32. t.add(x);
  33. }
  34. set.retainAll(t);
  35. }
  36. res.addAll(set);
  37. Collections.sort(res);
  38. return res;
  39. }
  40. }

6042. 统计圆内格点数目

给你一个二维整数数组 circles ,其中 circles[i] = [xi, yi, ri] 表示网格上圆心为 (xi, yi) 且半径为 ri 的第 i 个圆,返回出现在 至少一个 圆内的 格点数目
注意:

  • 格点 是指整数坐标对应的点。
  • 圆周上的点 也被视为出现在圆内的点。

示例 1:
image.png
输入:circles = [[2,2,1]] 输出:5 解释: 给定的圆如上图所示。 出现在圆内的格点为 (1, 2)、(2, 1)、(2, 2)、(2, 3) 和 (3, 2),在图中用绿色标识。 像 (1, 1) 和 (1, 3) 这样用红色标识的点,并未出现在圆内。 因此,出现在至少一个圆内的格点数目是 5 。
示例 2:
image.png
输入:circles = [[2,2,2],[3,4,1]] 输出:16 解释: 给定的圆如上图所示。 共有 16 个格点出现在至少一个圆内。 其中部分点的坐标是 (0, 2)、(2, 0)、(2, 4)、(3, 2) 和 (4, 4) 。

提示:

  • 1 <= circles.length <= 200
  • circles[i].length == 3
  • 1 <= xi, yi <= 100
  • 1 <= ri <= min(xi, yi)

思路:
范围不大,暴力找点即可
时间复杂度:O(n3), n <= 200

  1. class Solution {
  2. public int countLatticePoints(int[][] circles) {
  3. boolean[][] st = new boolean[300][300];
  4. for (int[] c : circles) {
  5. int x = c[0], y = c[1], r = c[2];
  6. for (int i = x - r; i <= x + r; i++) {
  7. for (int j = y - r; j <= y + r; j++) {
  8. if (check(i, j, x, y, r))
  9. st[i][j] = true;
  10. }
  11. }
  12. }
  13. int cnt = 0;
  14. for (int i = 0; i < 300; i++) {
  15. for (int j = 0; j < 300; j++) {
  16. if (st[i][j])
  17. cnt++;
  18. }
  19. }
  20. return cnt;
  21. }
  22. boolean check(int x1, int y1, int x2, int y2, int r) {
  23. int x = (x1 - x2), y = (y1 - y2);
  24. if (x * x + y * y <= r * r)
  25. return true;
  26. else
  27. return false;
  28. }
  29. }
  30. // 更简单的写法
  31. class Solution {
  32. public int countLatticePoints(int[][] circles) {
  33. int ret = 0;
  34. for(int x = 0;x <= 200;x++){
  35. for(int y = 0;y <= 200;y++){
  36. for(int[] c : circles){
  37. if((c[0] - x) * (c[0] - x) + (c[1] - y) * (c[1] - y) <= c[2]*c[2]){
  38. ret++;
  39. break;
  40. }
  41. }
  42. }
  43. }
  44. return ret;
  45. }
  46. }

6043. 统计包含每个点的矩形数目

给你一个二维整数数组 rectangles ,其中 rectangles[i] = [li, hi] 表示第 i 个矩形长为 li 高为 hi 。给你一个二维整数数组 points ,其中 points[j] = [xj, yj] 是坐标为 (xj, yj) 的一个点。
第 i 个矩形的 左下角 在 (0, 0) 处,右上角 在 (li, hi) 。
请你返回一个整数数组 _count ,长度为 points.length,其中 count[j]是 包含 _j 个点的矩形数目。
如果 0 <= xj <= li 且 0 <= yj <= hi ,那么我们说第 i 个矩形包含第 j 个点。如果一个点刚好在矩形的 边上 ,这个点也被视为被矩形包含。

示例 1:
image.png
输入:rectangles = [[1,2],[2,3],[2,5]], points = [[2,1],[1,4]] 输出:[2,1] 解释: 第一个矩形不包含任何点。 第二个矩形只包含一个点 (2, 1) 。 第三个矩形包含点 (2, 1) 和 (1, 4) 。 包含点 (2, 1) 的矩形数目为 2 。 包含点 (1, 4) 的矩形数目为 1 。 所以,我们返回 [2, 1] 。
示例 2:
image.png
输入:rectangles = [[1,1],[2,2],[3,3]], points = [[1,3],[1,1]] 输出:[1,3] 解释: 第一个矩形只包含点 (1, 1) 。 第二个矩形只包含点 (1, 1) 。 第三个矩形包含点 (1, 3) 和 (1, 1) 。 包含点 (1, 3) 的矩形数目为 1 。 包含点 (1, 1) 的矩形数目为 3 。 所以,我们返回 [1, 3] 。

提示:

  • 1 <= rectangles.length, points.length <= 5 * 104
  • rectangles[i].length == points[j].length == 2
  • 1 <= li, xj <= 109
  • 1 <= hi, yj <= 100
  • 所有 rectangles 互不相同
  • 所有 points 互不相同

思路:
hy的范围都很小,而lx的范围很大,需要离散化
然后用二维差分即可
时间复杂度:O(nlogn)
空间复杂度:O(n)

  1. class Solution {
  2. TreeSet<Integer> set = new TreeSet<>();
  3. Map<Integer, Integer> map = new HashMap<>();
  4. public int[] countRectangles(int[][] r, int[][] points) {
  5. int n = points.length;
  6. int[] res = new int[n];
  7. for (int[] x : r) {
  8. set.add(x[0]);
  9. set.add(x[0] + 1);
  10. }
  11. for (int[] p : points) {
  12. int x = p[0], y = p[1];
  13. set.add(x);
  14. }
  15. map.put(0, 0);
  16. int idx = 1;
  17. for (int x : set)
  18. if (x != 0)
  19. map.put(x, idx++);
  20. int row = map.size();
  21. int[][] a = new int[row + 1][110];
  22. for (int[] p : r) {
  23. int x = map.get(p[0]), y = p[1];
  24. a[0][0]++;
  25. a[0][y + 1]--;
  26. a[x + 1][0]--;
  27. a[x + 1][y + 1]++;
  28. }
  29. for (int i = 0; i <= row; i++) {
  30. for (int j = 0; j < 110; j++) {
  31. if (i > 0)
  32. a[i][j] += a[i - 1][j];
  33. if (j > 0)
  34. a[i][j] += a[i][j - 1];
  35. if (i > 0 && j > 0)
  36. a[i][j] -= a[i - 1][j - 1];
  37. }
  38. }
  39. for (int i = 0; i < n; i++) {
  40. int x = map.get(points[i][0]), y = points[i][1];
  41. res[i] = a[x][y];
  42. }
  43. return res;
  44. }
  45. }
  46. // 更简单的写法
  47. class Solution {
  48. public int[] countRectangles(int[][] rectangles, int[][] points) {
  49. int n = rectangles.length, Q = points.length;
  50. int[][] a = new int[n + Q][];
  51. for (int i = 0; i < n; i++) {
  52. a[i] = new int[]{rectangles[i][0], rectangles[i][1]};
  53. }
  54. for (int i = 0; i < Q; i++) {
  55. a[i + n] = new int[]{points[i][0], points[i][1], i};
  56. }
  57. Arrays.sort(a, (o1, o2) -> {
  58. if (o1[0] != o2[0])
  59. return o2[0] - o1[0];
  60. else
  61. return o1.length - o2.length;
  62. });
  63. int[] res = new int[Q];
  64. int[] cnt = new int[110];
  65. for (int[] p : a) {
  66. if (p.length == 3)
  67. res[p[2]] = cnt[p[1]];
  68. else {
  69. for (int i = 0; i <= p[1]; i++)
  70. cnt[i]++;
  71. }
  72. }
  73. return res;
  74. }
  75. }

6044. 花期内花的数目

给你一个下标从 0 开始的二维整数数组 flowers ,其中 flowers[i] = [starti, endi] 表示第 i 朵花的 花期 从 starti 到 endi (都 包含)。同时给你一个下标从 0 开始大小为 n 的整数数组 persons ,persons[i] 是第 i 个人来看花的时间。
请你返回一个大小为 n 的整数数组_ _answer ,其中 answer[i]是第 i 个人到达时在花期内花的 数目

示例 1:
image.png
输入:flowers = [[1,6],[3,7],[9,12],[4,13]], persons = [2,3,7,11] 输出:[1,2,2,2] 解释:上图展示了每朵花的花期时间,和每个人的到达时间。 对每个人,我们返回他们到达时在花期内花的数目。
示例 2:
image.png
输入:flowers = [[1,10],[3,3]], persons = [3,3,2] 输出:[2,2,1] 解释:上图展示了每朵花的花期时间,和每个人的到达时间。 对每个人,我们返回他们到达时在花期内花的数目。

提示:

  • 1 <= flowers.length <= 5 * 104
  • flowers[i].length == 2
  • 1 <= starti <= endi <= 109
  • 1 <= persons.length <= 5 * 104
  • 1 <= persons[i] <= 109

思路:
离散化 + 差分
时间复杂度:O(nlogn)
空间复杂度:O(n)

  1. class Solution {
  2. TreeSet<Integer> set = new TreeSet<>();
  3. Map<Integer, Integer> map = new HashMap<>();
  4. public int[] fullBloomFlowers(int[][] f, int[] p) {
  5. for (int[] x : f) {
  6. set.add(x[0]);
  7. set.add(x[1] + 1);
  8. }
  9. for (int x : p) {
  10. set.add(x);
  11. }
  12. int idx = 0;
  13. for (int x : set)
  14. map.put(x, idx++);
  15. int[] a = new int[idx];
  16. for (int[] x : f) {
  17. a[map.get(x[0])]++;
  18. a[map.get(x[1] + 1)]--;
  19. }
  20. for (int i = 1; i < idx; i++)
  21. a[i] += a[i - 1];
  22. int[] res = new int[p.length];
  23. for (int i = 0; i < p.length; i++) {
  24. res[i] = a[map.get(p[i])];
  25. }
  26. return res;
  27. }
  28. }
  1. // 更简单的写法
  2. class Solution {
  3. TreeMap<Integer, Integer> map = new TreeMap<>();
  4. public int[] fullBloomFlowers(int[][] f, int[] p) {
  5. for (int[] x : f) {
  6. map.merge(x[0], 1, Integer::sum);
  7. map.merge(x[1] + 1, -1, Integer::sum);
  8. }
  9. for (int x : p)
  10. map.merge(x, 0, Integer::sum);
  11. int pre = 0;
  12. for (int x : map.keySet()) {
  13. pre += map.get(x);
  14. map.put(x, pre);
  15. }
  16. int[] res = new int[p.length];
  17. for (int i = 0; i < p.length; i++) {
  18. res[i] = map.get(p[i]);
  19. }
  20. return res;
  21. }
  22. }
  1. // 扫描线
  2. class Solution {
  3. public int[] fullBloomFlowers(int[][] flowers, int[] persons) {
  4. int n = flowers.length, m = persons.length;
  5. int[][] a = new int[2 * n + m][];
  6. for (int i = 0; i < n; i++) {
  7. int l = flowers[i][0], r = flowers[i][1];
  8. a[i] = new int[]{l, 1};
  9. a[i + n] = new int[]{r + 1, -1};
  10. }
  11. for (int i = 0, j = 2 * n; i < m; i++, j++)
  12. a[j] = new int[]{persons[i], 0, i};
  13. Arrays.sort(a, (o1, o2) -> {
  14. if (o1[0] != o2[0])
  15. return o1[0] - o2[0];
  16. else
  17. return o1.length - o2.length;
  18. });
  19. int[] res = new int[m];
  20. int pre = 0;
  21. for (int i = 0; i < 2 * n + m; i++) {
  22. pre += a[i][1];
  23. if (a[i].length == 3)
  24. res[a[i][2]] = pre;
  25. }
  26. return res;
  27. }
  28. }