本文参考自《剑指offer》一书,代码采用Java语言。html
更多:《剑指Offer》Java实现合集 java
输入两个链表,找出它们的第一个公共结点。post
蛮力法:遍历第一个链表的结点,每到一个结点,就在第二个链表上遍历每一个结点,判断是否相等。时间复杂度为O(m*n),效率低;测试
使用栈:因为公共结点出如今尾部,因此用两个栈分别放入两个链表中的结点,从尾结点开始出栈比较。时间复杂度O(m+n),空间复杂度O(m+n)。this
利用长度关系:计算两个链表的长度之差,长链表先走相差的步数,以后长短链表同时遍历,找到的第一个相同的结点就是第一个公共结点。url
利用两个指针:一个指针顺序遍历list1和list2,另外一个指针顺序遍历list2和list1,(这样两指针可以保证最终同时走到尾结点),两个指针找到的第一个相同结点就是第一个公共结点。指针
测试算例 htm
1.功能测试(有/无公共结点;公共结点分别在链表的中间,头结点和尾结点)blog
2.特殊测试(头结点为null)get
//题目:输入两个链表,找出它们的第一个公共结点。 public class FirstCommonNodesInLists { public class ListNode{ int val; ListNode next = null; ListNode(int val) { this.val = val; } } //方法1:利用长度关系 public ListNode findFirstCommonNode1(ListNode pHead1, ListNode pHead2) { int length1 = getLength(pHead1); int length2 = getLength(pHead2); int lengthDif = length1-length2; ListNode longList = pHead1; ListNode shortList = pHead2; if(lengthDif<0){ longList = pHead2; shortList = pHead1; lengthDif = -lengthDif; } for(int i=0;i<lengthDif;i++) longList = longList.next; while(longList!=null && longList!=shortList ){ longList=longList.next; shortList=shortList.next; } return longList; //没有公共结点恰好是null } private int getLength(ListNode head){ int len=0; while(head!=null){ len++; head=head.next; } return len; } //方法2:两个指针,p1顺序遍历list1和list2;p2顺序遍历list2和list1;最终必定会相遇 public ListNode findFirstCommonNode2(ListNode pHead1, ListNode pHead2) { ListNode p1=pHead1; ListNode p2=pHead2; while(p1!=p2){ p1= p1==null ? pHead2 : p1.next; p2= p2==null ? pHead1 : p2.next; } return p1; } }
1.因为有共同结点时,后面的链表是重合的,因此这道题关键是要保证最后同时遍历到达尾结点,所以就有了后面三种方法:
利用栈的先进后出实现同时到达;
利用长度关系,长链表先行几步,实现同时到达;
两个指针同时遍历两个链表,一个先list1后list2,另外一个则相反,也能够实现同时到达。