public List<Point> findConvexHull(Point[] points) {
        if (points.length < 2) {
            return Arrays.asList(points);
        }

        //find the lowest point in the plane. If there are multiple lowest points
        //then pick the leftmost one.
        Point start = points[0];
        for (int i = 1; i < points.length; i++) {
            if (start.y > points[i].y) {
                start = points[i];
            } else if (start.y == points[i].y && start.x > points[i].x) {
                start = points[i];
            }
        }

        sortToHandleCollinear(points, start);

        Stack<Point> stack = new Stack<>();
        stack.push(points[0]);
        stack.push(points[1]);
        for (int i = 2; i < points.length; i++) {
            Point top = stack.pop();
            //second point will always be in answer so this will never cause empty stack exception.
            //as long as points[i] is on right of vector stack.peek() -> top keep getting rid of top of stack.
            while (crossProduct(stack.peek(), top, points[i]) < 0) {
                top = stack.pop();
            }
            stack.push(top);
            stack.push(points[i]);
        }
        return new ArrayList<>(stack);
    }
@author Tushar Roy
Date 10/11/2107

Convex hull or convex envelope of a set X of points in the Euclidean plane or in a Euclidean space
(or, more generally, in an affine space over the reals) is the smallest convex set that contains X.

Graham scan finds all vertices of the convex hull ordered along its boundary.

Time complexity O(nlogn)
Space complexity O(n)

References
https://leetcode.com/problems/erect-the-fence/description/
https://en.wikipedia.org/wiki/Convex_hull
https://en.wikipedia.org/wiki/Graham_scan
https://discuss.leetcode.com/topic/89336/java-graham-scan-with-adapted-sorting-to-deal-with-collinear-points
src/com/interview/geometry/GrahamScanConvexHull.java