public void Solve(System.Drawing.Graphics g, List <System.Drawing.PointF> pointList)
        {
            // Insert your code here.

            //Add all the points to a SortedList sorted by x-value
            //        List<PointF> slist = new List<PointF>();
            //        for (int i = 0; i < pointList.Count; i++)
            //        {
            //            if (!slist.Contains(pointList[i]))
            //            {
            //                slist.Add(pointList[i]);
            //            }
            //        }

            System.Collections.Generic.
            HashSet <PointF> hashPoints = new HashSet <PointF>();

            for (int i = 0; i < pointList.Count; i++)
            {
                hashPoints.Add(pointList[i]);
            }
            List <PointF> slist = ((IEnumerable <PointF>)hashPoints).ToList <PointF>();

            slist.Sort(new XComparer());

            //testing sorting visually
            //       drawList(g, slist);
            //Start timer
            //    timeUp = DateTime.Now.AddSeconds(5);

            //Recursively divide and conqueror
            LList hull = divAndCon(g, slist);

            drawLList(g, hull, new Pen(Color.Blue));
        }
        private void drawLList(Graphics g, LList hull, Pen pen)
        {
            //Font font = new Font("Arial", 10);
            //Brush brush = new SolidBrush(Color.SteelBlue);
            //g.DrawString("" + hull.Count, font, brush, new PointF(0F, 0F));
            LLNode temp = hull.LeftMost;

            if (hull.Count > 1)
            {
                do
                {
                    //g.DrawEllipse(pen, temp.Point.X, temp.Point.Y, 5, 5);
                    g.DrawLine(pen, temp.Point, temp.Next.Point);
                    temp = temp.Next;
                }while (temp.Point != hull.LeftMost.Point);
            }
        }
        private LList divAndCon(Graphics g, List <PointF> slist)
        {
            if (slist.Count > 1)
            {
                //Find middle
                int    mid  = slist.Count / 2;
                float  midX = slist[mid].X;
                PointF minY = slist[0];
                PointF maxY = slist[0];

                //Separate into left and right lists
                List <PointF> leftList  = new List <PointF>();
                List <PointF> rightList = new List <PointF>();
                for (int i = 0; i < slist.Count; i++)
                {
                    if (slist[i].X <= midX)
                    {
                        leftList.Add(slist[i]);
                        if (slist[i].Y < minY.Y)
                        {
                            minY = slist[i];
                        }
                        if (slist[i].Y > maxY.Y)
                        {
                            maxY = slist[i];
                        }
                    }
                    else
                    {
                        rightList.Add(slist[i]);
                    }
                }

                //if all points were added to the left list
                if (rightList.Count <= 0)
                {
                    LList skipper = new LList();
                    skipper.LeftMost       = new LLNode(minY);
                    skipper.RightMost      = new LLNode(maxY);
                    skipper.LeftMost.Next  = skipper.RightMost;
                    skipper.LeftMost.Prev  = skipper.RightMost;
                    skipper.RightMost.Next = skipper.LeftMost;
                    skipper.RightMost.Prev = skipper.LeftMost;
                    if (skipper.LeftMost.Point == skipper.RightMost.Point)
                    {
                        skipper.Count = 1;
                    }
                    else
                    {
                        skipper.Count = 2;
                    }

                    return(skipper);
                }

                LList leftLL  = divAndCon(g, leftList);
                LList rightLL = divAndCon(g, rightList);

                return(combine(g, leftLL, rightLL));
            }
            else
            {
                LList  llist = new LList();
                LLNode one   = new LLNode(slist[0]);
                one.Next        = one;
                one.Prev        = one;
                llist.LeftMost  = one;
                llist.RightMost = one;
                llist.Count     = 1;

                return(llist);
            }
        }
        private LList combine(Graphics g, LList leftLL, LList rightLL)
        {
            //place holders for solution points
            //(to manipulate next/prev pointers after completed testing)
            LLNode left    = leftLL.RightMost;
            LLNode right   = rightLL.LeftMost;
            LLNode topLSol = left;
            LLNode topRSol = right;
            LLNode botLSol = left;
            LLNode botRSol = right;

            //Test top
            Boolean found = false;
            Boolean acceptRight;
            Boolean acceptLeft;

            while (!found)
            {
                acceptRight = false;
                acceptLeft  = false;
                double m = (left.dY - right.dY) / (left.dX - right.dX);
                double b = (-m * left.dX) + left.dY;

                acceptRight = true;
                if (rightLL.Count > 1)
                {
                    LLNode testRight = right.Next;
                    if (m * testRight.dX + b - testRight.dY < 0)
                    {
                        right       = testRight;
                        acceptRight = false;
                    }
                    else
                    {
                        if (rightLL.Count > 2)
                        {
                            testRight = right.Prev;
                            if (m * testRight.dX + b - testRight.dY < 0)
                            {
                                right       = testRight;
                                acceptRight = false;
                            }
                        }
                    }
                }
                if (acceptRight)
                {
                    acceptLeft = true;
                    if (leftLL.Count > 1)
                    {
                        LLNode testLeft = left.Prev;
                        if (m * testLeft.dX + b - testLeft.dY < 0)
                        {
                            left       = testLeft;
                            acceptLeft = false;
                        }
                        else
                        {
                            if (leftLL.Count > 2)
                            {
                                testLeft = left.Next;
                                if (m * testLeft.dX + b - testLeft.dY < 0)
                                {
                                    left       = testLeft;
                                    acceptLeft = false;
                                }
                            }
                        }
                    }
                    if (acceptLeft)
                    {
                        topLSol = left;
                        topRSol = right;
                        found   = true;
                    }
                }
            }

            //Test bottom
            found = false;
            left  = leftLL.RightMost;
            right = rightLL.LeftMost;
            while (!found)
            {
                acceptRight = false;
                acceptLeft  = false;
                double m = (left.dY - right.dY) / (left.dX - right.dX);
                double b = (-m * left.dX) + left.dY;

                acceptRight = true;
                if (rightLL.Count > 1)
                {
                    LLNode testRight = right.Prev;
                    if (m * testRight.dX + b - testRight.dY > 0)
                    {
                        right       = testRight;
                        acceptRight = false;
                    }
                    else
                    {
                        if (rightLL.Count > 2)
                        {
                            testRight = right.Next;
                            if (m * testRight.dX + b - testRight.dY > 0)
                            {
                                right       = testRight;
                                acceptRight = false;
                            }
                        }
                    }
                }

                if (acceptRight)
                {
                    acceptLeft = true;
                    if (leftLL.Count > 1)
                    {
                        LLNode testLeft = left.Next;
                        if (m * testLeft.dX + b - testLeft.dY > 0)
                        {
                            left       = testLeft;
                            acceptLeft = false;
                        }
                        else
                        {
                            if (leftLL.Count > 2)
                            {
                                testLeft = left.Prev;
                                if (m * testLeft.dX + b - testLeft.dY > 0)
                                {
                                    left       = testLeft;
                                    acceptLeft = false;
                                }
                            }
                        }
                    }
                    if (acceptLeft)
                    {
                        botLSol = left;
                        botRSol = right;
                        found   = true;
                    }
                }
            }

            //Change pointers
            topLSol.Prev = topRSol;
            topRSol.Next = topLSol;
            botLSol.Next = botRSol;
            botRSol.Prev = botLSol;

            //update leftmost and rightmost pointers in a new LList
            LList nList = new LList();

            nList.LeftMost = topLSol;
            while (nList.LeftMost.Prev.dX < nList.LeftMost.dX)
            {
                nList.LeftMost = nList.LeftMost.Prev;
            }
            nList.RightMost = botRSol;
            while (nList.RightMost.Next.dX > nList.RightMost.dX)
            {
                nList.RightMost = nList.RightMost.Next;
            }
            nList.UpdateCount();

            return(nList);
        }