题目描述
给你一个数组 points
,其中 points[i] = [xi, yi]
,表示第 i
个点在二维平面上的坐标。多个点可能会有 相同 的坐标。
同时给你一个数组 queries
,其中 queries[j] = [xj, yj, rj]
,表示一个圆心在 (xj, yj)
且半径为 rj
的圆。
对于每一个查询 queries[j]
,计算在第 j
个圆 内 点的数目。如果一个点在圆的 边界上 ,我们同样认为它在圆 内 。
请你返回一个数组 answer
,其中 answer[j]
是第 j
个查询的答案。
EX1.
输入:points = [[1,3],[3,3],[5,3],[2,2]], queries = [[2,3,1],[4,3,1],[1,1,2]] 输出:[3,2,2] 解释:所有的点和圆如上图所示。 queries[0] 是绿色的圆,queries[1] 是红色的圆,queries[2] 是蓝色的圆。
EX2.
输入:points = [[1,1],[2,2],[3,3],[4,4],[5,5]], queries = [[1,2,2],[2,2,2],[4,3,2],[4,3,3]] 输出:[2,3,2,4] 解释:所有的点和圆如上图所示。 queries[0] 是绿色的圆,queries[1] 是红色的圆,queries[2] 是蓝色的圆,queries[3] 是紫色的圆。
提示
1 <= points.length <= 500
points[i].length == 2
0 <= xi, yi <= 500
1 <= queries.length <= 500
queries[j].length == 3
0 <= xj, yj <= 500
1 <= rj <= 500
- 所有的坐标都是整数。
代码实现
C语言
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//返回的矩阵是动态分配定义的,假设调用后会被free掉
int distance(int x1,int y1,int x2,int y2)//返回两个二维平面的点之间距离的平方
{
int distance;
distance = ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
return distance;
}
int* countPoints(int** points, int pointsSize, int* pointsColSize, int** queries, int queriesSize, int* queriesColSize, int* returnSize)//Point的ColSize为2,queriers的ColSize为3,下面代码将直接用数字表示,实际上真正的代码规范应该全都用变量名来调用
{
int i;//两个循环变量定义
int j;
int *answer=(int*)malloc(sizeof(int)*queriesSize);//根据给出的圆的数目多少来动态分配定义返回的数组
memset(answer,0,sizeof(int)*queriesSize);//昨天刚刚学到的用于初始化动态数组的memset函数
int dis;//定义新变量,追求可读性,将圆心和点的距离平方记录下来
for(i=0;i<queriesSize;i++)//第一层循环遍历每个圆
{
for(j=0;j<pointsSize;j++)//第二层循环对每个圆遍历每一个点
{
dis=distance(queries[i][0],queries[i][1],points[j][0],points[j][1]);//自定义函数调用
if(dis<=queries[i][2]*queries[i][2])
{
answer[i]++;//若点在该圆内,计数器+1
}
}
}
*returnSize=queriesSize;//这一步有点重要,之前编译一直错误或者输出错误就是因为漏了这一句,但是具体作用是什么呢?
return answer;
}
思路:
第一次读题,没读懂。第二次配合图像读读懂了,第一个思路就是两个循环,第一个循环遍历所有圆,第二个循环对每个单独圆遍历每个点。遇到了几个问题,第一趟代码写完,编译没过。第一个错是说前面的distance计算不能用squr函数,尽管我引入了<math.h>,后面换个思想,发现也不用那么精细,就用平方值就足够,而且还能避免开平方出现浮点数导致精度损失(看题解才了解到的,当时没想那么多)。第二个问题,输出的数组没有大小,后面发现是漏了:
*returnSize=queriesSize;//当然也是看了题解才懂的
这句话的原理是什么,我没弄懂,喂给AI之后,得到的回复是:
关于您提到的疑问:
- `*returnSize=queriesSize;` 这行代码的作用是设置输出参数`returnSize`的值。在C语言中,函数可以通过输出参数(通常是指针)来返回额外的信息。在这个函数中,`returnSize`指针被用来告知调用者返回数组`answer`的大小,这样调用者就知道需要为`answer`数组分配多少空间,并且在使用完毕后知道何时可以释放这个数组。
这时候才知道设计的牛逼之处!!!使用指针(数组)作为函数参数,避免传值导致另创副本,然后得到的returnSize就是answer的Size,这时候输出才会有长度,也便于随后调用者的free操作!但是还有一个小小疑问:
为什么没有这行代码,数组的数组就没有长度了?
继续喂给AI,再次学到新东西:
//
在C语言中,数组本身不包含其长度的信息。数组的长度必须由程序员在编写代码时明确跟踪和传递,因为数组在传递给函数时,其长度信息不会自动包含在内。这是C语言的一个特性,与数组的传递和表示方式有关。
当您在C语言中定义一个数组,如下所示:
```c
int array[10];
```
编译器会为这个数组分配一个连续的内存空间,但数组本身不会存储其长度。当你将数组作为参数传递给函数时,实际上传递的是指向数组首元素的指针,而数组的长度信息不会随之传递。
例如,当你调用一个函数:
```c
void someFunction(int arr[]) {
// 在这里,编译器不知道arr的长度
}
```
`someFunction`接收到的只是一个指针,它不知道这个数组的长度。因此,如果你需要在函数内部使用数组的长度,你必须以参数的形式显式传递它。这就是为什么在处理数组的函数中,你经常会看到额外的参数用来表示数组的长度。
在您提供的代码示例中,`countPoints`函数返回一个指向整数数组的指针,这个数组包含了每个查询的结果。由于数组长度信息不会随指针自动传递,所以需要`returnSize`参数来显式传递这个信息。调用者需要知道这个长度,以便正确地处理返回的数组,例如遍历它或最终释放其内存。
如果没有`returnSize`参数,调用者将无法知道返回数组的长度,这将导致无法正确地使用该数组,也没有办法正确地释放分配的内存,从而可能导致内存泄漏或其他潜在的错误。因此,`returnSize`参数是必要的,以确保数组可以被正确和安全地使用。
//
原来输入输出数组的时候,并不会并带传入数组的长度,需要另外设置参数来表示数组长度...怪不得很多题目都是数组和长度分两个参数传入参数!然后回到题目本身,answer的长度很显然就是queris的长度,所以用queriesSize就没什么疑问了,但是前面的代码不能出现*returnSize,因为这时候还是一个为止值,不会报错,但是输出不对。还要说的一点是*returnSize表示的是returnSize指向的地址的值,表示return的长度(有点绕),大概意思就是,当做指针来用,要加上*号,表示地址指向的地方的值(大概是个int?)。
总结
本来想今天早上写的,结果今天早上又忍不住刷手机,结果中午的时候推到下午,下午的时候又突发奇想想去English Corner...感觉还蛮好玩的,一共发言了三次嘿嘿,不知道听感怎么样,反正讲感还挺好的,而且还交到了朋友。btw,真的高水平,感觉十个人里五六个人雅思都可以7.5+(当然不包括我)。老师态度也很和善(好像是中亚的?),也很耐心,很温柔嘿嘿。然后就没写力扣...包括原本计划要写的大统赛论文也没写,然后现在力扣写到这已经晚上9:03。
还是回到这道题本身吧,这种解法在题解区貌似被称为暴力求解法?然后好像到这大家都开始关注内存占用量和运行时间了,然后看到题解区有用所谓二分法查找的,但我看不懂,之前貌似听过科普,但真正coding实现还是不熟悉...明天看看,下次找机会补一下...这道题应该是暴力解和二分法的效率差不多,可能是数据量比较小吧,换作更高维度就未必了...
不管怎样,还是坚持下来了,然后平板今天也买了,心里没有什么顾虑的了,先趁着三分钟热度还在,卷他几天再说。加油!