public ListNode rotateRight(ListNode head, int k) {
   if (head == null) {
     return head;
   }
   int n = k;
   int listSize = 0;
   ListNode end = head;
   while (k > 0) {
     end = end.next;
     k--;
     listSize++;
     if (end == null) {
       k = n % listSize;
       end = head;
       while (k > 0) {
         end = end.next;
         k--;
       }
       break;
     }
   }
   if (head == end) {
     return head;
   }
   ListNode start = head;
   while (end.next != null) {
     end = end.next;
     start = start.next;
   }
   end.next = head;
   head = start.next;
   start.next = null;
   return head;
 }
 private void zip(ListNode l1, ListNode l2) {
   while (l2 != null) {
     ListNode temp = l1.next;
     l1.next = l2;
     l1 = temp;
     temp = l2.next;
     l2.next = l1;
     l2 = temp;
   }
 }
 private ListNode reverse(ListNode head) {
   ListNode pre = null;
   ListNode p = head;
   while (p != null) {
     ListNode temp = p.next;
     p.next = pre;
     pre = p;
     p = temp;
   }
   return pre;
 }
 private ListNode[] split(ListNode head) {
   ListNode[] lists = new ListNode[2];
   lists[0] = head;
   if (head == null || head.next == null) {
     return lists;
   }
   ListNode slow = head;
   ListNode fast = head.next.next;
   while (fast != null) {
     slow = slow.next;
     if (fast.next == null) {
       break;
     }
     fast = fast.next.next;
   }
   lists[1] = slow.next;
   slow.next = null;
   return lists;
 }
  /**
   * 1. get catch point with two points(fast/slow) 2. split the cycle on that point 3. get the
   * intersection/joint node
   *
   * <p>如果允许修改每个node的val,可以用染色的方法 node = head while(node != null) { node.val = 999999;
   * if(node.next.val == 999999) return node.next; }
   *
   * @param head
   * @return
   */
  public ListNode detectCycle(ListNode head) {
    if (head == null || head.next == null) return null;
    LC_141_DetectCycle detector = new LC_141_DetectCycle();
    ListNode p = detector.getCatchPoint(head);
    if (p == null) return null;

    // split the cycle on the catch point, then get the intersection node
    ListNode head2 = p.next;
    p.next = null;
    LC_160_GetIntersectionNode inst = new LC_160_GetIntersectionNode();
    return inst.getIntersectionNode(head, head2);

    // another way is a little magic
    // suppose the distance between head and joint point is K, then it can be
    // proved that the catch point is also K distance far from the joint.
    /*
    ListNode p1 = head;
    while(p1 != p) {
        p1 = p1.next;
        p = p.next;
    }
    return p;
    */
  }
 public ListNode partition(ListNode head, int x) {
   ListNode lessHead = null;
   ListNode lessTail = null;
   ListNode greaterHead = null;
   ListNode greaterTail = null;
   ListNode p = head;
   while (p != null) {
     if (p.val < x) {
       if (lessHead == null) {
         lessHead = p;
       } else {
         lessTail.next = p;
       }
       lessTail = p;
     } else {
       if (greaterHead == null) {
         greaterHead = p;
       } else {
         greaterTail.next = p;
       }
       greaterTail = p;
     }
     p = p.next;
   }
   if (lessHead == null) {
     if (greaterTail != null) {
       greaterTail.next = null;
     }
     return greaterHead;
   } else {
     lessTail.next = greaterHead;
     if (greaterTail != null) {
       greaterTail.next = null;
     }
     return lessHead;
   }
 }
 public static void main(String[] args) {
   ListNode n1 = new ListNode(1);
   ListNode n2 = new ListNode(2);
   ListNode n3 = new ListNode(3);
   ListNode n4 = new ListNode(4);
   ListNode n5 = new ListNode(5);
   ListNode n6 = new ListNode(6);
   n1.next = n2;
   n2.next = n3;
   n3.next = n4;
   n4.next = n5;
   n5.next = n6;
   n6.next = n3;
   LC_141_DetectCycle inst = new LC_141_DetectCycle();
   System.out.println(inst.hasCycle(n1));
 }