两种方法对最近对问题的解释
背景描述:
终于,隔了将近一周,开始更新第二篇算法博客。今天的问题是最近对问题。问题描述如下:对于二维坐标系中的若干个点,从中判断出相距最近的两个点,并输出最近的这个距离。
我之前也翻看了很多篇博客,大家都解释的很好,但是都只是输出了最近的距离,而我希望这个程序不仅能输出最近距离,同时还能锁定是哪两个点得到的这个最近距离。于是,经过反复试错后,终于得到满意的结果,马不停蹄过来更新博客了。
蛮力法:
首先介绍蛮力法的思路。顾名思义,就是从第一个点开始,求它和第二个点之间的距离,然后求它和第三个点之间的距离,依次往后遍历。经过两重循环之后就可以得出最短的距离,同时锁定是哪两个点产生的。
可以设置两个一维数组,一个存储横坐标,另一个存储纵坐标,注意要两个数组彼此之间一一对应。完整算法如下(由于蛮力法较为简单,此处只给出算法部分,完整程序请参考下面分治法):
//返回最短长度,并得到该两个点在数组中的下标索引index1和index2
float Getclosedpoint(int *x, int *y, int n, int &index1, int &index2)
{
float min = (x[0] - x[1])*(x[0] - x[1]) + (y[0] - y[1])*(y[0] - y[1]);
float path;
for (int i = 0; i < n - 1; i++)
{
for (int j = i + 1; j < n; j++)
{
path = (x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]);
if (path <= min)
{
min = path;
index1 = i;
index2 = j;
}
}
}
return min;
}
蛮力法时间复杂度分析:
假设有n个点,则从外层循环是从第一个数字开始,循环到第n-1个数停止,共循环n-1次。内层循环一开始从第一个数开始,遍历求与后面所有的点之间的距离,共n-1次,最后一次循环从第n-1个数开始,求和第n个数之间的距离,执行1次。所以共执行1+2+…+(n-2)+(n-1)=n(n-1)/2;所以时间复杂度O(n2).
分治法
分治法顾名思义是分而治之,将一个大问题分解成几个小问题再逐个解决。对于最近对问题,分治法的思路如下:
1.首先将这些杂乱的点按照横坐标进行排序,然后取中间值mid将这堆点分成左右两部分。
2.分别对左边和右边的两小堆点集再次递归使用分治法,进而得到对应的最短距离d1和d2。
3.接下来处理mid中间线部分的情况。因为有一种可能就是距离最短的两个点一个在左区域一个在右区域。因此我们要对这种情况进行解决。办法是从刚才第二步中的两个结果中取最小值d,然后以步骤1中的中间值mid为基准,划分出宽度为2d的一个区域,然后将这个区域中的点进行蛮力法求得对应的最短距离d3。
4.最后将结果进行比较。
算法的完整程序如下:
#include<iostream>
#include<math.h>
#include<time.h>
using namespace std;
struct point {
int x, y;
};
//对数组R[low]到R[hjgh]之间进行一次划分,返回划分之后中枢轴的位置
int Partition(point *R,

最低0.47元/天 解锁文章
1万+





