题目

给你一个二维整数数组 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)

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-lattice-points-inside-a-circle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

将每个圆内的格点存到哈希集合中,方法是遍历圆的外切正方形,判断是否在圆内。最后集合的大小就是答案。集合的元素如果是数组,Set不会对相同点进行去重,那么使用一个矩阵更合适,可能在圆内的格点坐标都在[200,200]以内。见代码一

还可以直接遍历200*200内的点,是否存在于任意一个圆内。

代码

代码一 矩阵代替HashSet

  1. class Solution {
  2. public int countLatticePoints(int[][] circles) {
  3. int[][] mat = new int[201][201];
  4. for (int[] cir : circles) {
  5. int r = cir[2];
  6. int x = cir[0];
  7. int y = cir[1];
  8. for (int i = x - r; i <= x + r; i++) {
  9. for (int j = y - r; j <= y + r; j++) {
  10. if ((i - x) * (i - x) + (j - y) * (j - y) <= r * r) {
  11. mat[i][j] = 1;
  12. }
  13. }
  14. }
  15. }
  16. int ans = 0;
  17. for (int i = 0; i < 201; i++) {
  18. for (int j = 0; j < 201; j++) {
  19. if (mat[i][j] == 1) {
  20. ans++;
  21. }
  22. }
  23. }
  24. return ans;
  25. }
  26. }

代码二 使用HashSet

  1. class Solution {
  2. public int countLatticePoints(int[][] circles) {
  3. // set中不能存int[],不然每次new的数组不是一个引用,无法去重
  4. // 创建一个Point类,重写equals和hashCode就可以了
  5. // 但是实测慢很多
  6. Set<Point> set = new HashSet<>();
  7. for (int[] cir : circles) {
  8. int r = cir[2];
  9. int x = cir[0];
  10. int y = cir[1];
  11. for (int i = x - r; i <= x + r; i++) {
  12. for (int j = y - r; j <= y + r; j++) {
  13. if ((i - x) * (i - x) + (j - y) * (j - y) <= r * r) {
  14. set.add(new Point(i, j));
  15. }
  16. }
  17. }
  18. }
  19. return set.size();
  20. }
  21. class Point {
  22. int x = 0;
  23. int y = 0;
  24. public Point(int x, int y) {
  25. this.x = x;
  26. this.y = y;
  27. }
  28. @Override
  29. public boolean equals(Object o) {
  30. if (this == o) return true;
  31. if (o == null || getClass() != o.getClass()) return false;
  32. Point point = (Point) o;
  33. return x == point.x &&
  34. y == point.y;
  35. }
  36. @Override
  37. public int hashCode() {
  38. return Objects.hash(x, y);
  39. }
  40. }
  41. }

代码三 HashSet存List

正确的做法原来是将int[]换为List,这样相同的点就不会被认为是不同的了。但就是会慢很多,比代码二还要慢好几倍……

  1. class Solution {
  2. public int countLatticePoints(int[][] circles) {
  3. Set<List<Integer>> set = new HashSet<>();
  4. for (int[] cir : circles) {
  5. int r = cir[2];
  6. int x = cir[0];
  7. int y = cir[1];
  8. for (int i = x - r; i <= x + r; i++) {
  9. for (int j = y - r; j <= y + r; j++) {
  10. if ((i - x) * (i - x) + (j - y) * (j - y) <= r * r) {
  11. set.add(List.of(i, j));
  12. }
  13. }
  14. }
  15. }
  16. return set.size();
  17. }
  18. }