private ListNode quickSort(ListNode head, ListNode tail) {
            if (head == null) return null;
//            System.out.printf("%d, %d\n", head.val, tail == null ? 0 : tail.val);
//            head.printList();
            if (head.next == tail) return head;
            
            /**
             * choose first node as reference node(nRefer).
             * those with value smaller than <i>nRefer</i> will be added backward to <i>nHead</i>;
             * those with value bigger than <i>nRefer</i> will be added forward to <i>nTail</i>;
             * those with value equal <i>nRefer</i> will be added between <i>nRefer(included)</i> and <i>nRefer(included)</i>.
             *     N    N    N    N    N    N
             *     ^    ^         ^         ^  
             *     |    |         |         |
             *   nHead nRefer  nReferR    nTail
             */
            ListNode nRefer = head,  // reference node
                    nReferR = head;  // used to solve problem of repeated value
            head = head.next;
            nRefer.next = null;
            ListNode nHead = nRefer,
                    nTail = nRefer;
            do {
                ListNode tmpNode = head;
                head = head.next;
                
                if (tmpNode.val > nRefer.val) {
                    nTail.next = tmpNode;
                    nTail = tmpNode;
                } else if (tmpNode.val < nRefer.val) {
                    tmpNode.next = nHead;
                    nHead = tmpNode;
                } else {
                    tmpNode.next = nReferR.next;
                    nReferR.next = tmpNode;
                    if (nTail == nReferR) {
                        nTail = tmpNode;
                    }
                    nReferR = tmpNode;
                }
            } while (head != tail);
            nTail.next = tail;  // link tail to <i>nTail</i> to avoid breaking origin linked list
            
            /**
             * sort both right and left side, and return new head of left side.
             */
            if (nReferR != nTail) {
                nReferR.next = quickSort(nReferR.next, nTail.next);
            }
            return quickSort(nHead, nRefer.next);
        }