给点集求凸包的问题,有很多种算法
一个比较简单的算法是Monotone chain算法
它需要将点排序,在结点排好序的情况下是
的
lower
,正向遍历所有节点,判断当前节点在栈顶两个节点构成的向量的左边还是右边然后求凸包上界upper
,它需要反向遍历所有节点,步骤和上述一样。
判断新节点在向量左边还是右边需要用到叉积的一些知识。
由于本题中,在一条直线上的3个点也要算到边界里,所以cross
里的判断是>=0
,也因此upper
和lower
会有除了头尾之外的次,所以最后要去重
如果一条直线只算头尾的话,那么cross
里应该是>0
,并且最后返回lower[:-1]+upper[:-1]
即可
# Definition for a point. # class Point(object): # def __init__(self, a=0, b=0): # self.x = a # self.y = b class Solution(object): def outerTrees(self, points): """ :type points: List[Point] :rtype: List[Point] """ n = len(points) if n<=2: return points points = sorted(points, key=lambda x:(x.x,x.y)) def cross(i,j,k): x1,y1 = points[j].x-points[i].x,points[j].y-points[i].y x2,y2 = points[k].x-points[i].x,points[k].y-points[i].y return x1*y2-x2*y1>=0 lower = [] for i in xrange(n): while len(lower)>=2 and not cross(lower[-2],lower[-1],i): lower.pop() lower.append(i) upper = [] for i in xrange(n-1,-1,-1): while len(upper)>=2 and not cross(upper[-2],upper[-1],i): upper.pop() upper.append(i) return map(lambda x:points[x],set(lower)|set(upper))