/*
           Latest update: July 23, 2015
         * Leetcode question: Binary tree level order traversal
         *
         * 1. Practice more using Interface instead of actual class, like ArrayList in function return
         * 2. Change the return using IList<IList<int>>
         * 3. Test the code using leetcode online judge
         * Read the website about ArrayList vs List:
         * https://social.msdn.microsoft.com/Forums/vstudio/en-US/37c64e16-69e9-4935-abaa-ee8987230240/arraylist-vs-ilistobject?forum=netfxbcl&prof=required
         *   julia now understands the importance to use the interface, more generic, and less type casting,
         *   quick running time.
         *
         *   Leetcode online result:
         *   34 / 34 test cases passed.
             Status: Accepted
             Runtime: 536 ms
         */
        public static IList<IList<int>> levelOrder(TreeNode root)
        {
            IList<IList<int>> result = new List<IList<int>>();

            if (root == null)
                return (IList<IList<int>>)result;

            List<int> level = new List<int>();

            Queue<TreeNode> toVisit = new Queue<TreeNode>();

            toVisit.Enqueue(root);
            toVisit.Enqueue(null);

            while (true)
            {
                TreeNode cur = toVisit.Peek();
                toVisit.Dequeue();
                // end a level

                if (cur == null)
                {
                    List<int> list = new List<int>(); // julia: bug fix
                    list.AddRange(level);  // julia: bug fix
                    result.Add(list);

                    if (toVisit.Count == 0)
                        break;

                    // add a new End-Of-Level
                    level.Clear();

                    toVisit.Enqueue(null);
                }
                else
                {
                    level.Add(cur.val);
                    if (cur.left != null)
                        toVisit.Enqueue(cur.left);
                    if (cur.right != null)
                        toVisit.Enqueue(cur.right);
                }
            }

            return (IList<IList<int>>)result;
        }
        static void Main(string[] args)
        {
            /*Latest update: July 23, 2015
             * Test the code
             */
            TreeNode n1 = new TreeNode(1);
            n1.left = new TreeNode(2);
            n1.right = new TreeNode(3);
            n1.left.left = new TreeNode(4);
            n1.left.right = new TreeNode(5);
            n1.right.left = new TreeNode(6);
            n1.right.right = new TreeNode(7);

            IList<IList<int>> result3 = levelOrder(n1);
        }
        static void Main(string[] args)
        {
            /*Latest update: July 23, 2015
             * Test the code and then find a bug
             */
            TreeNode n1 = new TreeNode(1);
            n1.left = new TreeNode(2);
            n1.right = new TreeNode(3);
            n1.left.left = new TreeNode(4);
            n1.left.right = new TreeNode(5);
            n1.right.left = new TreeNode(6);
            n1.right.right = new TreeNode(7);

            ArrayList result = levelOrder_bugVersion(n1);

            /*
             * Try to fix the bug
             *
             */
            ArrayList result2 = levelOrder_bugFree(n1);
        }
 public TreeNode(int x)
 {
     val = x;
     left = null;
     right = null;
 }
        /**
         * source code from blog:
         * https://github.com/xiaoxq/leetcode-cpp/blob/master/src/BinaryTreeLevelOrderTraversal.cpp
         * convert from C++ to C#
         * julia's comment:
         * 1. check leetcode online judge, need to use IList<IList<int>>
         * 2. how to use queue for level order traversal, null point as level divider. Kind of tricky.
         *    first action before the loop, push first node into the queue, and then
         *    push level divider: null point
         *    design null pointer action: once null pointer is met, and then,
         *    finish the current level, go to next level:
         *    1. first, save the current level visited value into the result for return;
         *    2. second, check if the queue is empty -> yes, finish last level, ready to exit.
         *    3. third, prepare for next level:
         *       A: clear the container for current level info
         *       B: review facts: B.1. there is no null in the queue
         *                        B.2. there is only one level nodes in the queue, will be current level
         *          So, need to add level divider now.
         * 3. C# has a bug - share one arrayList object for each level,
         *    use clear method will not work out.
         *    lesson A: C# List.addAll <->  C# ArrayList.addRange
         */
        public static ArrayList levelOrder_bugVersion(TreeNode root)
        {
            ArrayList result = new ArrayList();

            if( root == null)
                return result;

            ArrayList level = new ArrayList();

            Queue<TreeNode> toVisit = new Queue<TreeNode>();

            toVisit.Enqueue( root );
            toVisit.Enqueue( null );

            while( true )
            {
                TreeNode cur = toVisit.Peek();
                toVisit.Dequeue();
                // end a level

                if( cur==null )
                {
                    result.Add( level );

                    if( toVisit.Count == 0 )
                        break;

                    // add a new End-Of-Level
                    level.Clear();   // julia's comment: C# bug, cannot share one object -
                                     //need to create new object for each level
                    toVisit.Enqueue( null );
                }
                else
                {
                    level.Add( cur.val );
                    if( cur.left != null)
                        toVisit.Enqueue( cur.left );
                    if( cur.right != null )
                        toVisit.Enqueue( cur.right );
                }
            }

            return result;
        }