这次想做一下关于实验一中convex hull的另一种解答方法
在原本的实验中我是利用了点到点之间的角度来画出convex hull的,每次取角度最小的点加入convex集合,这样就可以画出包括整个点的集合。所用的时间复杂度是square n,虽然解决了问题,时间复杂度不让人满意,下面我将描述一个时间复杂度为n的方法。
我们可以利用分治算法,将一个整体的大问题,拆分成两个小问题,也就是n个点变成两个n/2个点的问题于是就有 T(n)=2T(n/2)+?
为了合并两个子问题,我们需要将两个已经画出convex的n/2个点的图合并成一个n个点的画出convex的图
为此我们需要取出一些原有的连线,并且增加一些连线,来画出n个点的convex。其实经过简单的分析我们就能知道,我们要加的线其实只有两条,一条在a、b上端封顶,一条在a、b下端封底,然后再删去此时被包围的线就行,难点就在于如何找到我们要加入的两条线。
而这个“?”就是我们对两个子问题进行合并所需要的时间,我们要尽可能的减小他。
我们现在设两个小问题分别是a 、b(a中的点与b中的点不位于同一侧)
普通的想法自然是我将a与b中的每两个点进行连线,如果图中所有的点都在这个线的一边,那我们就可以判定,这个线就是convex的一员。但这样我们的时间复杂度还是square n, 没有进步。
算法:因为a与b中的点不在同一侧,所以我们能够画出一条直线,这条直线的左侧是a的点,右侧是b的点。我们找到a中与b中最靠近这条线的两个点a1,b1,并将这两个点连线,得到的线段a1b1必定与直线有交点,我们记下这个点的位置,然后移动将a1点变成与a1相连的两个点之中的一个(a2,a3),如果a2b1或a3b1的与直线的交点比a1b1与直线的交点更高,那就把a1替换掉,换成当前交点最高的线段,如果a1比另外两个交点更高我们就保留a1,然后再移动b1,移动方法与a1相同,如果a1b1当前已经是最高的线段了,那我们就认定a1b1就是我们的convex中的一员,这样我们就找到了封顶的线段。至于封底的线段,我们要找的就是与直线焦点最低的线段即可,方法相同。
这个算法巧妙在合并子问题的时候每一个点最多遍历一次,时间复杂度降低到了n
来源:CSDN
作者:wzj1212123
链接:https://blog.csdn.net/wzj1212123/article/details/104682942