蛮力法-分治法-处理最近对问题

两种方法对最近对问题的解释

背景描述:

  终于,隔了将近一周,开始更新第二篇算法博客。今天的问题是最近对问题。问题描述如下:对于二维坐标系中的若干个点,从中判断出相距最近的两个点,并输出最近的这个距离。
  我之前也翻看了很多篇博客,大家都解释的很好,但是都只是输出了最近的距离,而我希望这个程序不仅能输出最近距离,同时还能锁定是哪两个点得到的这个最近距离。于是,经过反复试错后,终于得到满意的结果,马不停蹄过来更新博客了。

蛮力法:

  首先介绍蛮力法的思路。顾名思义,就是从第一个点开始,求它和第二个点之间的距离,然后求它和第三个点之间的距离,依次往后遍历。经过两重循环之后就可以得出最短的距离,同时锁定是哪两个点产生的。
  可以设置两个一维数组,一个存储横坐标,另一个存储纵坐标,注意要两个数组彼此之间一一对应。完整算法如下(由于蛮力法较为简单,此处只给出算法部分,完整程序请参考下面分治法):

//返回最短长度,并得到该两个点在数组中的下标索引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, 
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值