不积跬步,无以至千里;不积小流,无以成江海

时间:2020-4-24 讨论:https://leetcode-cn.com/circle/discuss/F9IBSj/

A: 多个数组求交集

思路:

  1. 遍历数组
  2. 求交集
    1. 方式一, 暴力法全遍历统计各元素出现的次数
    2. 方式二, 每次仅保留重合部分, 或当重合部分为空时终止遍历
  1. function intersection(nums: number[][]): number[] {
  2. const n = nums.length;
  3. let ans = nums[0];
  4. for (let i = 1; i < n && ans.length; i++) {
  5. const cur = new Set(nums[i]);
  6. // get intersect
  7. ans = ans.filter(v => cur.has(v));
  8. }
  9. return ans.sort((a, b) => a - b);
  10. };

扩展:
image.png

  1. const a = [1, 2, 3], b = [2, 3, 4];
  2. // 并集
  3. let union = Array.from(new Set([...a, ...b]));
  4. // [1, 2, 3, 4]
  5. // 交集
  6. let intersection = a.filter(v => b.includes(v));
  7. // [2, 3]
  8. // 差集
  9. let subtract = a.filter(v => !b.includes(v));
  10. // [1]
  11. // 补集
  12. let complement = [...a.filter(v => !b.includes(v)), ...b.filter(v => !a.includes(v))]
  13. // [1, 4]

B: 统计圆内格点数目

由于 1 <= xi, yi <= 100 ;1 <= ri <= min(xi, yi) 可推到出所有圆在[0, 0] 到 [200, 200] 的区域中。
由于数据规模有限,可暴力计算出所有点。
优化思路:
不断缩小目标方形区域, 保证目标区域可以容纳所有圆。

  1. function countLatticePoints(circles: number[][]): number {
  2. const n = circles.length;
  3. let minX = Number.MAX_SAFE_INTEGER, minY = minX,
  4. maxX = Number.MIN_SAFE_INTEGER, maxY = maxX;
  5. let squares = [];
  6. for (let [x, y, r] of circles) {
  7. minX = Math.min(x - r, minX);
  8. minY = Math.min(y - r, minY);
  9. maxX = Math.max(x + r, maxX);
  10. maxY = Math.max(y + r, maxY);
  11. squares.push(r ** 2);
  12. }
  13. let ans = 0;
  14. for (let i = minX; i <= maxX; i++) {
  15. for (let j = minY; j <= maxY; j++) {
  16. for (let k = 0; k < n; k++) {
  17. const [x, y, ] = circles[k];
  18. if ((i - x) ** 2 + (j - y) ** 2 <= squares[k]) {
  19. ans++;
  20. break;
  21. }
  22. }
  23. }
  24. }
  25. return ans;
  26. };

总结: :::info

枚举坐标系中的点:

1828. 统计一个圆中点的数目
几何 https://leetcode-cn.com/tag/geometry/problemset/ ::: 反思:
以为会涉及比较复杂的几何知识,其实关键点在数据规模上

C: 统计包含每个点的矩形数目

思路: 枚举

  1. function countRectangles(rectangles: number[][], points: number[][]): number[] {
  2. const n = 101;
  3. let ymap = Array.from({ length: n }, v => []);
  4. for (let [x, y] of rectangles) {
  5. ymap[y].push(x);
  6. }
  7. for (let nums of ymap) {
  8. nums.sort((a, b) => a - b);
  9. }
  10. let ans = [];
  11. for (let [x, y] of points) {
  12. let count = 0;
  13. for (let h = y; h < n; h++) {
  14. const nums = ymap[h];
  15. let left = 0, right = nums.length;
  16. while (left < right) {
  17. let mid = (left + right) >> 1;
  18. if (x > nums[mid]) {
  19. left = mid + 1;
  20. } else {
  21. right = mid;
  22. }
  23. }
  24. count += (nums.length - right);
  25. }
  26. ans.push(count);
  27. }
  28. return ans;
  29. };

总结: :::info

关键:数据规模

:::

D: 花期内花的数目

思路:

  1. 差分, 考虑到数组会超时,优化为哈希表存放差分值
  2. 查询, 哈希表
    function fullBloomFlowers(flowers: number[][], persons: number[]): number[] {
     // 离散差分
     let hashMap = new Map();
     for (let [start, end] of flowers) {
         end++;
         hashMap.set(start, (hashMap.get(start) || 0) + 1);
         hashMap.set(end, (hashMap.get(end) || 0) - 1);
     }
     for (let p of persons) {
         if (!hashMap.has(p)) {
             hashMap.set(p, 0);
         }
     }
     let keys = Array.from(hashMap.keys()).sort((a, b) => a - b);
     let pre = 0;
     for (let k of keys) {
         pre += hashMap.get(k);
         hashMap.set(k, pre);
     }
     // 离散查询
     let ans = persons.map(v => hashMap.get(v));
     return ans;
    };
    

总结: :::info 离散化差分 + 离线查询
差分:
731. 我的日程安排表 II
732. 我的日程安排表 III
2015. 每段建筑物的平均高度
2021. 街上最亮的位置
2237. Count Positions on Street With Required Brightness
离线查询:
1697. 检查边长度限制的路径是否存在
1707. 与数组中元素的最大异或值
1847. 最近的房间 :::

启发

关注数据规模