找凸包的O(nlgn)算法
归约
已知问题A的复杂度,未知问题B,如果A的输入能在O(n)时间内转成B的输入,B求解后的输出可以在O(n)时间内转为A的输出,则B>=A,即B的下界为A
garham sacn
算法:O(nlgn)
- 找出LIL
- 对其余的点按照极角排序(toLeft),O(nlgn)
- 构造两个栈,按如下代码,最终S即为所求,O(n)
def scan:
S = deque([1,2])
T = deque([3,4,...,n])
while len(T) > 0:
u, v, w = S[-2], S[-1], T[-1]
if toLeft(u, v, w):
S.append(T.pop())
else:
S.pop()
return S
"""
复杂度分析:
A = len(S) + 2 * len(T) < 2 * n
if: len(S)++ len(T)-- 1-2=-1
else: len(S)-- -1
每一轮 A--
"""
x-sorted
算法:O(n),将Garham的极角排序改成横坐标排序
1.从右向左(想象LTL位于y轴负无穷)排序调用gram scan中的scan
2.从左向右排序调用garm scan中的scan
分治
算法:O(nlgn)
按横坐标二分,求两个n/2的子问题的凸包,将得到的两个凸包合并(O(n)),具体合并算法略
F(n) = 2 * F(n/2) + O(n)