题目描述
输入两个链表,找出它们的第一个公共节点。(链表非循环结构)
按照题目示例,公共节点指的是该节点内存地址相同,而非仅val值相同。链表节点结构如下:
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
解析
解法一:双重循环
- 思路:第一思路当然是双重循环遍历链表,但时间复杂度是O(MN)。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode headNodeB=headB;
if(headA==null || headB==null) return null;
while(headA!=null) {
while(headNodeB!=null){
if(headA.equals(headNodeB)) return headA;
headNodeB=headNodeB.next;
}
headA=headA.next;
headNodeB=headB;
}
return null;
}
解法二:比较长度
- 思路:若两个链表有公共节点,则从公共节点开始至链尾一定是相同的长度,所以可以遍历两个链表计算各自的长度,让较长的链表头节点先移动k步(k是二者的长度差),再逐节点比较是否相等。时间复杂度是O(M+N)
public ListNode getIntersectionNode2(ListNode headA, ListNode headB) {
if(headA==null || headB==null) return null;
ListNode nodeA=headA, nodeB=headB;
int lenA=0, lenB=0;
lenA=getLength(nodeA);
lenB=getLength(nodeB);
int k =lenA-lenB;
if(k==0){
return interNode(headA, headB);
}else if(k<0) {
headB = goforward(headB,-k);
return interNode(headA, headB);
}else{
headA = goforward(headA,k);
return interNode(headA, headB);
}
}
private int getLength(ListNode node) {
int length=0;
while(node!=null){
length++;
node=node.next;
}
return length;
}
private ListNode goforward(ListNode node,int n) {
for(int i=0;i<n;i++) {
node=node.next;
}
return node;
}
private ListNode interNode(ListNode nodeA, ListNode nodeB) {
while(nodeA!=null || nodeB!=null) {
if(nodeA.equals(nodeB)) return nodeA;
nodeA=nodeA.next;
nodeB=nodeB.next;
}
return null;
}
解法三:双指针法
- 思路:类似于追逐问题,时间复杂度O(M+N)
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA == null || headB == null) return null;
ListNode node1=headA;
ListNode node2=headB;
while (node1!=node2){
node1=(node1==null)? headB : node1.next;
node2=(node2==null)? headA : node2.next;
}
return node1;
}
主要考察的是解法三!