最糟糕的也是最容易想到的解法:对两个链表进行遍历,时间复杂度为O(mn)
改进解法:
对于单链表而言,从第一个公共结点开始,之后所有的结点都是重合的,不可能出现分叉
从两个链表的尾部进行遍历,最后一个相同的结点就是我们要找的结点。
但是单链表只能从前往后遍历,所以这里又用到了一个数据结构–栈
这里我们需要用到两个辅助栈,空间复杂度为O(m+n),时间复杂度为O(m+n);
第三种思路:我们首先得到两个链表的长度,较长的一个先走几步(多的几个),再同时遍历得到第一个公共结点,时间复杂度为O(m+n),空间效率提高了
代码:
package core;
/**问题描述:输入两个链表。找出他们的第一个公共结点。
* 单向链表的特点:两个链表有公共结点,肯定会有重复部分(Y而非X)
* Created by lxq on 2017/9/11.
*/
public class Problem1 {
public ListNode findFirstCommonNode(ListNode head1, ListNode head2) {
int len1 = getListLength(head1);
int len2 = getListLength(head2);
ListNode longListNde = null;
ListNode shortListNode = null;
int dif = 0;
if(len1>len2){
longListNde = head1;
shortListNode = head2;
dif = len1-len2;
}else {
longListNde = head2;
shortListNode = head1;
dif = len2-len1;
}
for(int i=0;i<dif;i++){
longListNde = longListNde.pNext;
}
while (longListNde!=null&&shortListNode!=null&&
longListNde!=shortListNode){
longListNde = longListNde.pNext;
shortListNode = shortListNode.pNext;
}
return longListNde;
}
private int getListLength(ListNode head) {
int length = 0;
if(head==null)
return length;
ListNode point = head;
while(point!=null){
point = point.pNext;
length++;
}
return length;
}
}
public static void main(String[] args){
ListNode head1 = new ListNode();
ListNode head2 = new ListNode();
ListNode two1 = new ListNode();
ListNode three1 = new ListNode();
ListNode four = new ListNode();
ListNode five = new ListNode();
ListNode two2 = new ListNode();
ListNode three2 = new ListNode();
head1.pNext = two1;
two1.pNext = three1;
three1.pNext = four;
four.pNext = five;
head2.pNext = two2;
two2.pNext = three2;
three2.pNext = four;
four.pNext = five;
head1.data = 1;
two1.data = 2;
three1.data = 3;
four.data = 6;
five.data = 7;
head2.data = 4;
two2.data = 5;
three2.data = 9;
Problem1 problem1 = new Problem1();
System.out.println(problem1.findFirstCommonNode(head1,head2).data);
}