问题:两个链表的第一个公共结点
要求:输入两个链表,找出它们的第一个公共结点。
1 struct ListNode { 2 int val; 3 struct ListNode *next; 4 ListNode(int x) : 5 val(x), next(NULL) { 6 } 7 };* 8 class Solution { 9 public: 10 ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { 11 12 } 13 };
首先明确:
想到两个链表的交叉情况,我们第一意识就是图 2所示的情况。然而从单向链表的节点结构来看,如果两个链表有公共节点,那么这两个链表从某一个节点开始,他们的next都指向同一个节点,且之后所有的节点都会重合,如图1所示,才是两个单向链表交叉的情况,即Y型交叉。
解题方法:
方法一: 暴力法,挨个遍历,时间复杂度O(m*n);
方法二: 辅助栈,为两个链表建立两个辅助栈,将每个链表遍历到各自的辅助栈,栈顶元素就是链表尾节点,然后比较栈顶两个元素是否相同,若相同,弹出栈顶元素继续比较,知道找到最后一个相同的元素,时间复杂度和空间复杂度都为O(m+n);
方法三:先遍历两个链表得到各自长度,求得两个链表的长度差 lengthDif 。首先遍历较长链表 lengthDif 步,然后两个链表同时开始遍历,直到找到两个地址相同的元素。时间复杂度O(m+n),不需要辅助栈。
解题代码:
1 struct ListNode { 2 int val; 3 struct ListNode *next; 4 ListNode(int x) : 5 val(x), next(NULL) { 6 } 7 };* 8 class Solution { 9 public: 10 ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) { 11 auto length1 = getSize(pHead1); 12 auto length2 = getSize(pHead2); 13 int lengthDif = length1 - length2; 14 ListNode *pLong = pHead1; 15 ListNode *pShort = pHead2; 16 if(length1 < length2){ 17 pLong = pHead2; 18 pShort = pHead1; 19 lengthDif = length2 - length1; 20 } 21 22 for(int i=0; i<lengthDif; i++) 23 pLong = pLong->next; 24 25 while((pLong != nullptr) && (pShort != nullptr) && (pLong != pShort)){ 26 pLong = pLong->next; 27 pShort =pShort->next; 28 } 29 ListNode *pCommonNode = pLong; 30 return pCommonNode; 31 } 32 33 unsigned int getSize(ListNode *pHead){ 34 unsigned int size = 0; 35 ListNode *p = pHead; 36 while(p != nullptr){ 37 size++; 38 p = p->next; 39 } 40 return size; 41 } 42 };