力扣 160相交链表

一开始想到的暴力解法忽略了两链表不等长时,都从第一个元素开始遍历会失败解法1.暴力解法指针遍历链表,但是要记得若两链表不等长则不能只遍历一遍,则需要两个while形成两层遍历,则一链表为基,从起始遍历另一链表,相互比较。即对链表A中的每一个结点ai ,遍历整个链表 B 并检查链表 B 中是否存在结点和ai相同。class Solution {public: ListNode *g...
摘要由CSDN通过智能技术生成

一开始想到的暴力解法忽略了两链表不等长时,都从第一个元素开始遍历会失败

解法
1.暴力解法
指针遍历链表,但是要记得若两链表不等长则不能只遍历一遍,则需要两个while形成两层遍历,则一链表为基,从起始遍历另一链表,相互比较。即对链表A中的每一个结点ai ,遍历整个链表 B 并检查链表 B 中是否存在结点和ai相同。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA==NULL||headB==NULL)//无交点
        return NULL;
        while(headA)
        {   ListNode *p=headB;//注意其位置,每次循环都需重置
            if(headA==p) return headA;//注意返回为结点
            while(p->next)
            {
                p=p->next;
                if(headA==p) return headA;
            }
            headA=headA->next; 
        }
        return NULL;
       
    }
};

这种解法时间复杂度O(mn),太慢了,不建议使用。

解法2 哈希法
遍历链表 A 并将每个结点的地址/引用存储在哈希表中。然后检查链表 B 中的每一个结点 bi是否在哈希表中。若在则bi为相交结点。用到set(关联容器 键值类型相同,键唯一,则集合中不会有多个相同的键,对于此题可用)
此解法与暴力解法类似,只不过将结点存储在哈希表中,只需遍历一遍A即可

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA==NULL||headB==NULL)//无交点
        return NULL;
       set<ListNode *> s;
       while(headA)
       {
           s.insert(headA);//装入set
           headA=headA->next;
       }
       while(headB)
       {
           if(s.find(headB)!=s.end())//set的find函数返回一个迭代器,该迭代器指向键与head值相同的元素,若无则返回s.end()
           return headB;
           headB=headB->next;
       }
       return NULL;
    }
};

时间复杂度 : O(m+n)O(m+n)。
空间复杂度 : O(m)O(m) 或 O(n)O(n)。

解法三 双指针

  1. 创建两个指针 pA 和 pB,分别初始化为链表 A 和 B 的头结点。然后让它们向后逐结点遍历。

  2. 当 pA 到达链表的尾部时,将它重定位到链表 B 的头结点 (你没看错,就是链表 B); 类似的,当 pB 到达链表的尾部时,将它重定位到链表 A 的头结点。

  3. 若在某一时刻 pA 和 pB 相遇,则 pA/pB 为相交结点。

  4. 想弄清楚为什么这样可行, 可以考虑以下两个链表: A={1,3,5,7,9,11} 和 B={2,4,9,11},相交于结点 9。 由于 B.length (=4) < A.length (=6),pB比 pA 少经过 22 个结点,会先到达尾部。将 pB 重定向到 A 的头结点,pA 重定向到 B 的头结点后,pB 要比 pA 多走 2 个结点。因此,它们会同时到达交点。
    如果两个链表存在相交,它们末尾的结点必然相同。因此当 pA/pB到达链表结尾时,记录下链表 A/B 对应的元素。若最后元素不相同,则两个链表不相交。

这样用双指针就使两指针走相同的路程,弥补了链表长度的不同
即a + all +b = b + all + a (all是链表相交个数,a是A不相交个数,b是B不相交个数)

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA==NULL||headB==NULL)//无交点
        return NULL;
      ListNode *pa=headA;//当前指针
      ListNode *pb=headB;//当前指针
      while(pa!=pb)
      {
          pa=pa?pa->next:headB;
          pb=pb?pb->next:headA;
      }
      return pa;
    }
};

复杂度分析
时间复杂度 : O(m+n)O(m+n)。
空间复杂度 : O(1)O(1)。

三种方法第三种最优。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值