链表解题技巧:
1.额外数据结构记录(如哈希表)
2.快慢指针(快指针速度一般是慢指针的两倍)
本题解题步骤
1.先判断链表是否为环形链表,如果是,则返回入环的第一个结点,否则返回null
(1)哈希表解决
(2)快慢指针,关键点:快指针速度是慢指针的两倍,当快指针与慢指针相遇时,此时,新指针从头结点开始,慢指针从相遇点开始遍历,当新指针与慢指针相遇时,此结点即为入环的第一个结点。*
证明:
1.慢指针在第一圈时就与快指针相遇
证:假设慢指针在第二圈时才相遇
一个简单的理解,当慢指针来到入环的第一个结点处时,此时快指针肯定已经在环内,当慢指针跑完了一个环,快指针肯定跑完了两个环,因此不可能在慢指针跑完了一圈后再相遇。
假设从环结点处(入环的第一个结点,以下简称环结点)断开,根据环的长度可以分为三种情况:
(1)环的长度等于链表的长度的一半
显而易见,快指针与慢指针相遇在环结点处,当慢指针走完一个环时,新结点从头结点开始正好也走到环结点处。
(2)环的长度大于链表的长度的一半
(3)环的长度小于链表的长度的一半
public class Solution {
public ListNode detectCycle(ListNode head) {
if(head==null||head.next==null)
return null;
ListNode fast=head.next.next;
ListNode slow=head.next;
while(fast!=null&&fast.next!=null&&slow!=fast){
slow=slow.next;
System.out.println(slow.val);
fast=fast.next.next;
}
if(fast==null||fast.next==null)
return null;
fast=head;
while(fast!=slow){
slow=slow.next;
fast=fast.next;
}
return slow;
}
}
2.两个链表都为单链表时,求其相交结点
因为ListNode的定义,每个结点只有一个next结点,因此当链表1走完长度len时,开始遍历链表2,一定会找到相交的结点
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode cur1=headA;
ListNode cur2=headB;
if(cur1==null||cur2==null)
return null;
int n=0;
while(cur1!=null){
n++;
cur1=cur1.next;
}
while(cur2!=null){
n--;
cur2=cur2.next;
}
cur1=n<0?headB:headA;
cur2=n<0?headA:headB;
while(n!=0){
cur1=cur1.next;
if(n<0)
n++;
else
n--;
}
while(cur1!=cur2){
cur1=cur1.next;
cur2=cur2.next;
}
return cur1;
}
}
3.一个为单链表,一个为双链表时,这两个链表肯定没有相交结点
谨记:ListNode定义一个结点只有一个next结点
4.两个都为环形链表
三种情况:
***:5.总代码:***
public class cycleCommon {
public static void main(String[] args) {
//输入举例
Scanner sc=new Scanner(System.in);
int n=sc.nextInt(),m=sc.nextInt(),k=sc.nextInt();
ListNode headA=new ListNode(0);
ListNode headB=new ListNode(0);
ListNode cur=null;
ListNode common=null;
for(int i=0;i<n;i++){
cur=new ListNode(sc.nextInt());
if(i==n-k){
common=cur;
}
headA.next=cur;
headA=headA.next;
}
for(int i=0;i<m-k;i++){
cur=new ListNode(sc.nextInt());
headB.next=cur;
headB=headB.next;
}
headB.next=common;
System.out.println(common);
// 先判断是否有环
ListNode loop1=hasCycle(headA);
ListNode loop2=hasCycle(headB);
if(loop1==null&&loop2==null){//都为单链表
System.out.println(getCommonNode(headA,headB));
}else if(loop1!=null&&loop2!=null){ //都为环形链表
System.out.println(getInsertNode(headA,headB,loop1,loop2));
}
else{
System.out.println("null");
}
}
//是否有环
public static ListNode hasCycle(ListNode head){
if(head==null||head.next==null)
return null;
ListNode fast=head.next.next;
ListNode slow=head.next;
while(fast!=null&&fast.next!=null&&slow!=fast){
slow=slow.next;
System.out.println(slow.val);
fast=fast.next.next;
}
if(fast==null||fast.next==null)
return null;
fast=head;
while(fast!=slow){
slow=slow.next;
fast=fast.next;
}
return slow;
}
//单链表的第一个相交结点
public static ListNode getCommonNode( ListNode headA,ListNode headB){
ListNode cur1=headA;
ListNode cur2=headB;
if(cur1==null||cur2==null)
return null;
int n=0;
while(cur1!=null){
n++;
cur1=cur1.next;
}
while(cur2!=null){
n--;
cur2=cur2.next;
}
cur1=n<0?headB:headA;
cur2=n<0?headA:headB;
while(n!=0){
cur1=cur1.next;
if(n<0)
n++;
else
n--;
}
while(cur1!=cur2){
cur1=cur1.next;
cur2=cur2.next;
}
return cur1;
}
//环形链表的第一个相交结点
public static ListNode getInsertNode( ListNode headA, ListNode headB, ListNode loop1, ListNode loop2){
if(headA==null||headB==null)
return null;
if(loop1==loop2){
ListNode cur1=headA;
ListNode cur2=headB;
int n=0;
while(cur1!=loop1){
n++;
cur1=cur1.next;
}
while(cur2!=loop2){
n--;
cur2=cur2.next;
}
cur1=n<0?headB:headA;
cur2=n<0?headA:headB;
while(n!=0){
cur1=cur1.next;
if(n<0)
n++;
else
n--;
}
while(cur1!=cur2){
cur1=cur1.next;
cur2=cur2.next;
}
return cur1;
}else{
ListNode cur=loop1;
while(loop1!=cur){
if(loop1==loop2){
return loop2;
}
loop1=loop1.next;
}
return null;
}
}
}
class ListNode{
ListNode next;
int val;
public ListNode(int val){
this.val=val;
next=null;
}
}
有错欢迎大家指正(假装有人看系列)