链表相关问题分析part1(寻找公共节点,是否有环)

25 篇文章 0 订阅
10 篇文章 0 订阅
这篇文章主要是分析一下最近做过的两道leetcode链表相关的题目,这两道题目有很大的相似,分别为LeetCode160题和LeetCode141题。

首先来看一下160题(相交链表):图片来源于LeetCode
图片来源于LeetCode

思路一:

看到这道题目首先第一想法就是遍历其中一个链表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;
    }
};

思路二

思路一其实是比较容易想到的,思路二我是参考了别人的想法后才写出来的。具体做法如下:

  1. 定义两个指针pA,pB,开始分别指向链表A和B,开始遍历。
  2. 如果 pA到了末尾,则 pA = headB 继续遍历 如果 pB 到了末尾,则 pB = headA 继续遍历。
  3. 若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),较为复杂,所以我没有去实现它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值