两个链表的第一个公共结点

Posted 穿过雾的阴霾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了两个链表的第一个公共结点相关的知识,希望对你有一定的参考价值。

使用空间存储节点的解法

class Solution 
public:
    set<ListNode*> s;
    ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) 
        for (auto i = headA; i ; i=i->next)
            s.insert(i);
        for (auto i = headB; i ; i=i->next)
            if(s.count(i))  return i;
        return NULL;
    
;

不使用空间,解法一

如果有公共结点肯定是在后面重叠,且后面部分都是共同的。

  • 先计算出两个链表的长度,可以让比较长的先走两个链表长度之差的步数,两个再一起走。
/**
 * Definition for singly-linked list.
 * struct ListNode 
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) 
 * ;
 */
/**
 * Definition for singly-linked list.
 * struct ListNode 
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) 
 * ;
 */
class Solution 
public:
    ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) 
        int len1=0,len2=0;
        auto i=headA,j=headB;
        for (auto i = headA; i ; i=i->next) len1++;
        for (auto i = headB; i ; i=i->next) len2++;
        if(len1<len2)
        
            swap(len1,len2);
            swap(i,j);
        
        int offset=len1-len2;
        for (int t = 0; t < offset; t ++ )  i=i->next;
        while(i)
        
            if(i==j)    return i;
            i=i->next;
            j=j->next;
        
        return NULL;
    
;

剑指Offer 两个链表的第一个公共结点

  题目链接:两个链表的第一个公共结点

  思路:如果两个链表有公共结点,则第一个公共结点以及之后的所有结点都是重合的,即至少它们的尾结点是重合的。因为两个链表长度不一定相等,所以同步遍历时不能保证两个链表同时到达尾结点。假设一个链表比另一个多k个结点,先在长的链表上遍历k个结点即尾部对齐,再同步遍历,保证同时到达尾结点,即同时到达第一个公共结点。也就是说,同步遍历时第一个相同结点就是第一个公共结点。

  步骤:

  1 如果两个链表至少有一个是空,则返回null。

  2 分别获取两个链表的长度len1和len2。

  3 通过比较两个链表的长度来获取长度差k,并使长链表遍历k个结点。

  4 通过同步遍历来查找第一个公共结点,如果查找到公共结点,则返回该结点。

  5 返回null。

  时间复杂度:O(len1+len2)。

  Java代码:

 1 /*
 2 public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }*/
10 public class Solution {
11     public ListNode FindFirstCommonNode(ListNode list1, ListNode list2) {
12         // 如果两个链表至少有一个是空,则返回null
13         if (list1 == null || list2 == null) {
14             return null;
15         }
16         
17         // 分别获取两个链表的长度len1和len2
18         int len1 = getListLength(list1);
19         int len2 = getListLength(list2);
20         
21         // 通过比较两个链表的长度来获取长度差k,并使长链表遍历k个结点
22         if (len1 > len2) {
23             list1 = walkSteps(list1, len1 - len2);
24         } else {
25             list2 = walkSteps(list2, len2 - len1);
26         }
27         
28         // 通过同步遍历来查找第一个公共结点,如果查找到公共结点,则返回该结点
29         while (list1 != null) {
30             if (list1 == list2) {
31                 return list1;
32             }
33             
34             list1 = list1.next;
35             list2 = list2.next;
36         }
37         
38         // 返回null
39         return null;
40     }
41     
42     // 获取链表长度
43     private int getListLength(ListNode list) {
44         int len = 1;
45         while (list.next != null) {
46             list = list.next;
47             len++;
48         }
49         
50         return len;
51     }
52     
53     // 获取当前结点走了k步之后的结点
54     private ListNode walkSteps(ListNode list, int k) {
55         while (k-- > 0) {
56             list = list.next;
57         }
58         
59         return list;
60     }
61 }

 

  参考资料

  [编程题]两个链表的第一个公共结点

  《2017年数据结构联考复习指导》P46-47

以上是关于两个链表的第一个公共结点的主要内容,如果未能解决你的问题,请参考以下文章

两个链表的第一个公共结点

剑指offer两个链表的第一个公共结点

两个链表的第一个公共结点

链表两个链表的第一个公共结点

两个链表的第一个公共结点

剑指offer---两个链表的第一个公共结点