这篇文章主要是分析一下最近做过的两道leetcode链表相关的题目,这两道题目有很大的相似,分别为LeetCode160题和LeetCode141题。
首先来看一下160题(相交链表):
思路一:
看到这道题目首先第一想法就是遍历其中一个链表A,用一个哈希表来存储每一个节点,然后在遍历另外一个链表B,判断B中是否存在一个节点的next节点存在于刚存储的哈希表中,若存在,则找到了相交节点,反之则两个链表不相交。
代码实现如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
unordered_set<ListNode*>sa;
for(auto p=headA;p!=nullptr;p=p->next)
{
sa.insert(p);
}
for(auto q=headB;q!=nullptr;q=q->next)
{
if(sa.find(q)!=sa.end())
{
return q;
}
}
return nullptr;
}
};
思路二
思路一其实是比较容易想到的,思路二我是参考了别人的想法后才写出来的。具体做法如下:
- 定义两个指针pA,pB,开始分别指向链表A和B,开始遍历。
- 如果 pA到了末尾,则 pA = headB 继续遍历 如果 pB 到了末尾,则 pB = headA 继续遍历。
- 若pA=pB,说明找到了两个链表的相交节点,即为pA。
具体实现可以看动画了解:动画演示整个过程
实现代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *pa=headA,*pb=headB;
if(pa==0||pb==0)return 0;
while(pa!=pb)
{
if(pa==0)pa=headB;
else pa=pa->next;
if(pb==0)pb=headA;
else pb=pb->next;
}
return pa;
}
};
如果链表没有相交,最后会出现pA=pB=nullptr
,这样也是可以跳出while循环的,完全不用担心会出现死循环。
总结:以上两种方法时间复杂度均为O(n),但是第二种方法的空间复杂度为O(1),且实现较为简单
本题也可以暴力破解,对其中一个链表A的每一个节点判断是否存在链表B中某个节点与其相同,若存在说明链表相交;反之则不相交。这种方法时间复杂度为O(n2),较为复杂,所以我没有去实现它。