这是一道比较综合的题目。将链表中关于环和相交的问题聚集在一起了,关键是要思路清晰。
思路如下:
/*
* 判断链表是否有环
* 1 如果一个有环一个无环,则肯定不相较
* 2 如果都无环,则遍历到尾部,看看最后一个节点是否相等即可
* 如果要找到第一个相交的点,则让长的链表先走len1-len2步,再同时走,找到相等的节点即可
* 3 如果都有环,则先找到各自的环入口点(快慢指针,第一次相遇后,快指针从头节点开始,每次走一步,慢指针继续向前走一步,直至再次相遇)
* 如果两个入口点相等,则肯定相交
* 如果要找到第一个相交的点,则需要让长的链表(从头节点到相交的节点)先走len1-len2步,然后同时走,找到相等的点即可
* 如果两个入口点不相等,则选其中一个相交点,继续向后走,看看 是否会经历另外一个相交点,如果经历了,则相交,否则不相交
*/
具体代码如下:
public boolean chkInter(ListNode head1, ListNode head2, int adjust0, int adjust1) {
if(head1==null || head2==null) return false;
ListNode node1 = chkLoop(head1);
ListNode node2 = chkLoop(head2);
//判断是否有环
if(node1==null && node2==null) { //两个都是无环链表
while(head1.next!=null) {
head1 = head1.next;
}
while(head2.next !=null) {
head2 = head2.next;
}
if(head1==head2) {
return true;
} else {
return false;
}
} else if(node1!=null && node2!=null) {//两个都是有环链表
//node1和node2是环的入口点
if(node1==node2) {
return true;
} else {
ListNode cur = node1.next;
while(cur!=node1) {
if(cur == node2) { //相交
return true;
}
cur = cur.next;
}
//不相交
return false;
}
} else { //一个有环一个无环
return false;
}
}
private ListNode chkLoop(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while(fast!=null && fast.next!=null) {
slow = slow.next;
fast = fast.next.next;
if(slow==fast) {
break;
}
}
//没有环则返回null
if(fast==null || fast.next==null) return null;
fast = head;
while(slow!=fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}