题目描述
编写一个程序,找到两个单链表相交的起始节点。
注意:
- 如果两个链表没有交点,返回 null.
- 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
解题思路:
- 数据结构链表章节经典的题目(对于链表的操作) (注意:节点相同而非节点值相同)
解法一:
- 暴力解法:对链表A中的每一个结点遍历整个链表B并检查链表B中是否存在结点相同
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null){
return null;
}
if(headB==null){
return null;
}
ListNode B = null;
while(headA!=null){
B = headB;
while(B!=null){
if(headA==B)
return headA;
B = B.next;
}
headA=headA.next;
}
return null;
}
- 时间复杂度:O(mn)
- 空间复杂度:O(1)
解法二
- 借助HashSet,遍历链表A,然后判断链表B中与A相同的节点输出
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA==null){
return null;
}
if(headB==null){
return null;
}
HashSet<ListNode> set = new HashSet<>();
while(headA!=null){
set.add(headA);
headA = headA.next;
}
while(headB!=null){
if(set.contains(headB))
return headB;
headB = headB.next;
}
return null;
}
- 时间复杂度:O(m+n)
- 空间复杂度:O(m)或O(n)
解法三
-
根据链表长度进行解题,长链表先遍历至跟短链表相同长度,同时遍历判断节点是否相等,如果没有相等节点则返回null
下图参考自力扣题解“数据结构和算法”用户的题解:
代码如下:
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lengthA = length(headA);
int lengthB = length(headB);
if(lengthA>lengthB){
for(int i=0;i<lengthA-lengthB;i++)
headA = headA.next;
}
else{
for(int i=0;i<lengthB-lengthA;i++)
headB = headB.next;
}
while(headA!=null&&headB!=null){
if(headA==headB)
return headA;
headA = headA.next;
headB = headB.next;
}
return null;
}
public static int length(ListNode l){
int length = 0;
while(l!=null){
l=l.next;
length++;
}
return length;
}
时间复杂度:O(m)或O(n)
空间复杂度:O(1)
解法四
- 双指针法:具体解析参考题解
- 如果两个指针相等则代表两指针共同指向的就是相交的地方
- 如果两链表没有相交,则就是A+B=B+A的情况,则两指针会同时指向NULL跳出循环返回NULL
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA;
ListNode B = headB;
while(A!=B){
A = (A==null)? headB:A.next;
B = (B==null)? headA:B.next;
}
return A;
}
- 时间复杂度:O(m+n)
- 空间复杂度:O(1)