import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashSet;
import java.util.Set;
class Solution {
/**
* 构建链式结构
*
* @param head
* @param position
*/
private void custructNodeList(ListNode head, int position) {
int index = 0;
ListNode currentNode = head;
ListNode positionNode = null;
ListNode lastNode = null;
if (position >= 0) {
while (currentNode != null) {
lastNode = currentNode;
if (index == position) {
positionNode = currentNode;
}
currentNode = currentNode.next;
index++;
}
}
if (lastNode != null && positionNode != null) {
lastNode.next = positionNode;
}
}
public boolean hasCycle(ListNode head, int position) {
custructNodeList(head, position);
//return hasCycle(head);
return hasCycle2(head);
}
/**
* 给定一个链表,判断链表中是否有环。
* <p>
* 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置
*(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
* <p>
* 示例 1:
* <p>
* 输入:head = [3,2,0,-4], pos = 1
* 输出:true
* 解释:链表中有一个环,其尾部连接到第二个节点。
* <p>
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/linked-list-cycle
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
/**
* 方法一:已经访问过的,再次访问到时存在环
*
* @param head
* @return
*/
public boolean hasCycle(ListNode head) {
Set<ListNode> hasVisited = new HashSet<>();
while (head != null) {
ListNode current = head;
if (hasVisited.contains(current)) {
return true;
} else {
hasVisited.add(current);
}
head = head.next;
}
return false;
}
/**
* 快慢指针,相遇则表示存在环
*
* @param head
* @return
*/
public boolean hasCycle2(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
public ListNode detectCycle(ListNode head, int position) {
custructNodeList(head, position);
return detectCycle(head);
}
/**
* 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
* <p>
* 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置
*(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
* <p>
* 说明:不允许修改给定的链表。
* 示例 1:
* 输入:head = [3,2,0,-4], pos = 1
* 输出:tail connects to node index 1
* 解释:链表中有一个环,其尾部连接到第二个节点。
* <p>
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/linked-list-cycle-ii
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
/**
* 记录是否访问
*
* @param head
* @return
*/
public ListNode detectCycle(ListNode head) {
Set<ListNode> visited = new HashSet<ListNode>();
ListNode node = head;
while (node != null) {
if (visited.contains(node)) {
return node;
}
visited.add(node);
node = node.next;
}
return null;
}
private ListNode getIntersect(ListNode head) {
ListNode tortoise = head;
ListNode hare = head;
// A fast pointer will either loop around a cycle and meet the slow
// pointer or reach the `null` at the end of a non-cyclic list.
while (hare != null && hare.next != null) {
tortoise = tortoise.next;
hare = hare.next.next;
if (tortoise == hare) {
return tortoise;
}
}
return null;
}
/**
* 双指针
*
* @param head
* @return
*/
public ListNode detectCycle2(ListNode head) {
if (head == null) {
return null;
}
// If there is a cycle, the fast/slow pointers will intersect at some
// node. Otherwise, there is no cycle, so we cannot find an e***ance to
// a cycle.
ListNode intersect = getIntersect(head);
if (intersect == null) {
return null;
}
// To find the e***ance to the cycle, we have two pointers traverse at
// the same speed -- one from the front of the list, and the other from
// the point of intersection.
ListNode ptr1 = head;
ListNode ptr2 = intersect;
while (ptr1 != ptr2) {
ptr1 = ptr1.next;
ptr2 = ptr2.next;
}
return ptr1;
}
}
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
@Override
public String toString() {
return "ListNode{" +
"val=" + val +
'}';
}
}
public class MainClass {
public static int[] stringToIntegerArray(String input) {
input = input.trim();
input = input.substring(1, input.length() - 1);
if (input.length() == 0) {
return new int[0];
}
String[] parts = input.split(",");
int[] output = new int[parts.length];
for (int index = 0; index < parts.length; index++) {
String part = parts[index].trim();
output[index] = Integer.parseInt(part);
}
return output;
}
public static ListNode stringToListNode(String input) {
// Generate array from the input
int[] nodeValues = stringToIntegerArray(input);
// Now convert that list into linked list
ListNode dummyRoot = new ListNode(0);
ListNode ptr = dummyRoot;
for (int item : nodeValues) {
ptr.next = new ListNode(item);
ptr = ptr.next;
}
return dummyRoot.next;
}
public static String listNodeToString(ListNode node) {
if (node == null) {
return "[]";
}
String result = "";
while (node != null) {
result += Integer.toString(node.val) + ", ";
node = node.next;
}
return "[" + result.substring(0, result.length() - 2) + "]";
}
public static String booleanToString(boolean input) {
return input ? "True" : "False";
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String line;
while ((line = in.readLine()) != null) {
ListNode head = stringToListNode(line);
line = in.readLine();
int pos = Integer.parseInt(line);
boolean ret = new Solution().hasCycle(head, pos);
String out = booleanToString(ret);
// ListNode ret = new Solution().detectCycle(head, pos);
// String out = listNodeToString(ret);
System.out.print(out);
}
}
}