973. 最接近原点的 K 个点-k数组维护+二分查找
给定一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点,并且是一个整数 k ,返回离原点 (0,0) 最近的 k 个点。
这里,平面上两点之间的距离是 欧几里德距离( √(x1 - x2)2 + (y1 - y2)2 )。
你可以按 任何顺序 返回答案。除了点坐标的顺序之外,答案 确保 是 唯一 的。
示例 1:
输入:points = [[1,3],[-2,2]], k = 1
输出:[[-2,2]]
解释:
(1, 3) 和原点之间的距离为 sqrt(10),
(-2, 2) 和原点之间的距离为 sqrt(8),
由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。
我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]。
示例 2:
输入:points = [[3,3],[5,-1],[-2,4]], k = 2
输出:[[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也会被接受。)
对于这题我们维护了一个数组长度为K得数组
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both indexned array and *columnSizes array must be malloced, assume caller calls free().
*/
int find_index(int *a,int size,int v){
int high=size-1;
int low=0;
if(a[size-1]<=v){
return -1;
}
else{
while(low<=high){
int mid=(high+low)/2;
if(a[mid]>v){
high=mid-1;
}
else{
low=mid+1;
}
}
return low;
}
}
int** kClosest(int** points, int pointsSize, int* pointsColSize, int k, int* returnSize, int** returnColumnSizes) {
int **a=(int **)malloc(sizeof(int*)*k);
int min_index[k];
int index_record[k];
*returnColumnSizes = malloc(sizeof(int) * k);
for(int i=0;i<k;i++){
a[i]=(int *)malloc(sizeof(int)*2);
}
for(int i=0;i<k;i++){
(*returnColumnSizes)[i] = 2;
}
for(int i=0;i<k;i++){
int z=points[i][0]*points[i][0]+points[i][1]*points[i][1];
min_index[i]=points[i][0]*points[i][0]+points[i][1]*points[i][1];
// printf("z %d ",z);
index_record[i]=i;
if(i==0){
continue;
}
else{
int j=i-1;
for(;j>=0;j--){
if(min_index[j]>z){
min_index[j+1]=min_index[j];
index_record[j+1]=index_record[j];
}
else{
break;
}
}
// printf("-- %d ",j);
if(j!=0){
min_index[j+1]=z;
index_record[j+1]=i;
}
if(j==0){
if(min_index[j]>z){
min_index[0]=z;
index_record[0]=i;
}
else{
min_index[j+1]=z;
index_record[j+1]=i;
}
}
// printf("j %d",j);
}
// for(int iz=0;iz<i;iz++){
// printf("*%d ",min_index[iz]);
// }
// printf("\n");
}
for(int i=k;i<pointsSize;i++){
int v=points[i][0]*points[i][0]+points[i][1]*points[i][1];
int find_index_min=find_index(min_index,k,v);
// printf(" find_index_min %d ",find_index_min);
if(find_index_min==-1){
continue;
}
else{
for(int j=k-1;j>find_index_min;j--){
min_index[j]=min_index[j-1];
index_record[j]=index_record[j-1];
}
min_index[find_index_min]=points[i][0]*points[i][0]+points[i][1]*points[i][1];
index_record[find_index_min]=i;
}
}
for(int i=0;i<k;i++){
a[i][0]=points[index_record[i]][0];
a[i][1]=points[index_record[i]][1];
}
*returnSize=k;
return a;
}
其运行情况如下:
当然上面这个方法是很粗糙的,而且有多余的内存消耗,博主发现,内存还可以优化,下面是优化后的代码:
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both indexned array and *columnSizes array must be malloced, assume caller calls free().
*/
int find_index(int *a,int size,int v){
int high=size-1;
int low=0;
if(a[size-1]<=v){
return -1;
}
else{
while(low<=high){
int mid=(high+low)/2;
if(a[mid]>v){
high=mid-1;
}
else{
low=mid+1;
}
}
return low;
}
}
int** kClosest(int** points, int pointsSize, int* pointsColSize, int k, int* returnSize, int** returnColumnSizes) {
int min_index[k];
*returnColumnSizes = malloc(sizeof(int) * k);
for(int i=0;i<k;i++){
(*returnColumnSizes)[i] = 2;
}
for(int i=0;i<k;i++){
int z=points[i][0]*points[i][0]+points[i][1]*points[i][1];
min_index[i]=points[i][0]*points[i][0]+points[i][1]*points[i][1];
// printf("z %d ",z);
int x=points[i][0];
int y=points[i][1];
if(i==0){
continue;
}
else{
int j=i-1;
for(;j>=0;j--){
if(min_index[j]>z){
min_index[j+1]=min_index[j];
points[j+1][0]=points[j][0];
points[j+1][1]=points[j][1];
}
else{
break;
}
}
// printf("-- %d ",j);
if(j!=0){
points[j+1][0]=x;
points[j+1][1]=y;
min_index[j+1]=z;
}
if(j==0){
if(min_index[j]>z){
min_index[0]=z;
points[0][0]=x;
points[0][1]=y;
}
else{
min_index[j+1]=z;
points[j+1][0]=x;
points[j+1][1]=y;
}
}
// printf("j %d",j);
}
// for(int iz=0;iz<i;iz++){
// printf("*%d ",min_index[iz]);
// }
// printf("\n");
}
for(int i=k;i<pointsSize;i++){
int v=points[i][0]*points[i][0]+points[i][1]*points[i][1];
int find_index_min=find_index(min_index,k,v);
// printf(" find_index_min %d ",find_index_min);
if(find_index_min==-1){
continue;
}
else{
for(int j=k-1;j>find_index_min;j--){
min_index[j]=min_index[j-1];
points[j][0]=points[j-1][0];
points[j][1]=points[j-1][1];
}
min_index[find_index_min]=points[i][0]*points[i][0]+points[i][1]*points[i][1];
points[find_index_min][0]=points[i][0];
points[find_index_min][1]=points[i][1];
}
}
*returnSize=k;
return points;
}
这个运行情况要多好了: