給定兩個單鏈表的頭節點head1和head2,如何判斷兩個鏈表是否相交?相交的話返回true,不想交的話返回false。
給定兩個鏈表的頭結點head1和head2(注意,另外兩個參數adjust0和adjust1用于調整數據,與本題求解無關)。請返回一個bool值代表它們是否相交。
思路
結合之前有環鏈表相交和無環鏈表相交 的思考, 我們需要先對鏈表的類型進行判斷. 如果兩個都是同一類型的鏈表,則重用之前的代碼進行判斷即可,如果一個是有環,一個是無環的鏈表,則它們不可能相交.
public class ChkIntersection {
public boolean chkInter(ListNode head1, ListNode head2, int adjust0, int adjust1) {
if(head1==null||head2==null)return false;
ListNode entry1=findCycleEntry(head1);
ListNode entry2=findCycleEntry(head2);
//兩個無環鏈表
if(entry1==null||entry2==null){
return chkIntersect(head1,head2);
}
//兩個有環鏈表
else if(entry1!=null&&entry2!=null){
if(entry1==entry2){
return true;
}
else{
ListNode backup=entry1;
do{
entry1=entry1.next;
}while(entry1!=entry2&&entry1!=backup);
return !(entry1==backup);
}
}
//一個有環一個無環
else return false;
}
//找到入環節點
private ListNode findCycleEntry(ListNode head){
if(head==null||head.next==null)return null;
ListNode fast=head,slow=head;
do{
slow=slow.next;
fast=fast.next.next;
}while(slow!=fast&&fast.next!=null&&fast.next.next!=null);
if(slow!=fast)return null;
slow=head;
while(slow!=fast){
fast=fast.next;
slow=slow.next;
}
return slow;
}
//查找無環鏈表相交情況
public boolean chkIntersect(ListNode headA, ListNode headB) {
// write code here
int lenA=getListLen(headA);
int lenB=getListLen(headB);
if(lenA==0||lenB==0)return false;
if(lenA<lenB){
headB=runKNode(headB,lenB-lenA);
}
else{
headA=runKNode(headA,lenA-lenB);
}
while(headA!=null&&headA!=headB){
headA=headA.next;
headB=headB.next;
}
return headA==null?false:true;
}
private int getListLen(ListNode head){
int len=0;
while(head!=null){
len++;
head=head.next;
}
return len;
}
private ListNode runKNode(ListNode head,int len){
for(int i=0;i<len;i++){
head=head.next;
}
return head;
}
}