版权声明:此文章为许诗宇所写,如需转载,请写下转载文章的地址 https://blog.csdn.net/xushiyu1996818/article/details/84026020
题目及测试
package pid160;
/* 相交链表
编写一个程序,找到两个单链表相交的起始节点。
例如,下面的两个链表:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在节点 c1 开始相交。
注意:
如果两个链表没有交点,返回 null.
在返回结果后,两个链表仍须保持原有的结构。
可假定整个链表结构中没有循环。
程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
致谢:
特别感谢 @stellari 添加此问题并创建所有测试用例。
*/
public class main {
public static void main(String[] args) {
ListNode c=new ListNode(0);
c.next=new ListNode(-1);
LinkList a=new LinkList(1);
a.addLast(2);
a.addLast(3);
a.first.next.next.next=c;
a.printList();
//test(a.first);
LinkList b=new LinkList(5);
b.addLast(6);
b.addLast(4);
b.addLast(2);
b.first.next.next.next.next=c;
b.printList();
test(a.first,b.first);
/*
LinkList c=new LinkList(1);
c.addLast(2);
c.addLast(2);
c.addLast(1);
c.printList();
//test(c.first);
LinkList d=new LinkList(1);
d.addLast(2);
d.addLast(3);
c.printList();
d.printList();
test(c.first,d.first);*/
}
private static void test(ListNode ito,ListNode ito2) {
Solution solution = new Solution();
ListNode rtn;
long begin = System.currentTimeMillis();
System.out.println();
//开始时打印数组
rtn=solution.getIntersectionNode(ito,ito2);//执行程序
long end = System.currentTimeMillis();
System.out.println("rtn=");
rtn.printNodeToEnd();
//System.out.println(":rtn" );
//System.out.print(rtn);
System.out.println();
System.out.println("耗时:" + (end - begin) + "ms");
System.out.println("-------------------");
}
}
解法1(成功,2ms,超快)
首先有一点非常重要,相交节点后的所有节点 (包括相交节点) 都是两个链表共享的。
我们将两个链表的右端对齐,长度较大的链表 的左端的 多出来的节点 肯定不是相交节点,所以我们不考虑左端的这一部分的节点
使用双指针算法,先遍历一遍两个链表的长度,再将两个指针指向两个链表头部,移动长的链表的指针,指向相同距离的位置,再两个指针一起走,如果指针相遇,则得到相同节点
package pid160;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null||headB==null){
return null;
}
int lengthA=0;
int lengthB=0;
ListNode now=headA;
while(now!=null){
lengthA++;
now=now.next;
}
now=headB;
while(now!=null){
lengthB++;
now=now.next;
}
ListNode nowA=headA;
ListNode nowB=headB;
if(lengthA>lengthB){
for(int i=0;i<lengthA-lengthB;i++){
nowA=nowA.next;
}
}
if(lengthA<lengthB){
for(int i=0;i<lengthB-lengthA;i++){
nowB=nowB.next;
}
}
ListNode result=null;
while(true){
if(nowA==nowB){
result=nowA;
break;
}
if(nowA==null||nowB==null){
break;
}
nowA=nowA.next;
nowB=nowB.next;
}
return result;
}
}
网上还有两种解法,都不太好
有以下几种思路:
(1)暴力破解,遍历链表A的所有节点,并且对于每个节点,都与链表B中的所有节点比较,退出条件是在B中找到第一个相等的节点。时间复杂度O(lengthA*lengthB),空间复杂度O(1)。
(2)哈希表。遍历链表A,并且将节点存储到哈希表中。接着遍历链表B,对于B中的每个节点,查找哈希表,如果在哈希表中找到了,说明是交集开始的那个节点。时间复杂度O(lengthA+lengthB),空间复杂度O(lengthA)或O(lengthB)。