@shawngao Thanks for the clear solution! One small improvement, we only need to track indices, instead of the actual Points. Here's the C++ version:

class Solution { private: vector<Point> points; struct comp{ bool operator() (Point a, Point b) { return a.x==b.x ? a.y<b.y : a.x<b.x; } }; int cross(int ai,int bi,int ci) { int bax=points[bi].x-points[ai].x; int bay=points[bi].y-points[ai].y; int bcx=points[bi].x-points[ci].x; int bcy=points[bi].y-points[ci].y; return bax*bcy-bay*bcx; } int dist(int ai,int bi) { int bax=points[bi].x-points[ai].x; int bay=points[bi].y-points[ai].y; return bax*bax+bay*bay; } public: vector<Point> outerTrees(vector<Point>& points) { this->points = points; set<Point,comp> pset; vector<Point> res; int n=points.size(), fi=0, ni=-1; for (int i=0; i<n; i++) if (points[i].x<points[fi].x) fi=i; int ci=fi; pset.insert(points[fi]); while (ci!=fi || ni==-1) { ni=0; for (int i=0; i<n; i++) { if (ci==i) continue; if (ni==i || cross(ci,i,ni)>0 || (cross(ci,i,ni)==0 & dist(ci,i)>dist(ci,ni))) { ni=i; } } for (int i=0; i<n; i++) { if (ci==i) continue; if (cross(ci,i,ni)==0) pset.insert(points[i]); } ci=ni; } for (Point p:pset) res.push_back(p); return res; } };Erect the Fence