20210604 每日一题 相交链表

题目

题目链接

代码

/**
 * 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) {
        
    }
};

方法一:哈希表

分析

寻找链表是否相交,可以使用哈希表存储链表节点,并
我们遍历链表 A A A B B B 的每个元素对比哈希表中元素。

  • 当前元素不在哈希表中,将当前元素存入哈希表;
  • 当前元素在哈希表中,返回当前元素;
  • 如果链表 A A A B B B 遍历结束,则两个链表不相交,返回 n u l l null null

代码

/**
 * 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*> hash;
        while(headA != nullptr || headB != nullptr) {
            if(headA != nullptr) {
                if(hash.count(headA)) {
                    return headA;
                } else {
                    hash.insert(headA);
                }
                headA = headA->next;
            }
            if(headB != nullptr) {
                if(hash.count(headB)) {
                    return headB;
                } else {
                    hash.insert(headB);
                }
                headB = headB->next;
            }
        }
        return nullptr;
    }
};

复杂度分析

  • 时间复杂度: O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n)),其中 m m m n n n 是链表 A A A B B B 的长度。哈希表可以在 O ( 1 ) O(1) O(1) 的时间进行查找。
  • 空间复杂度: O ( m + n ) O(m+n) O(m+n),空间复杂度主要取决于哈希表,哈希表中存储 A A A B B B 两个链表的元素,最多有 m + n m+n m+n 个元素。

分析

对以上代码进行优化,我们可以先遍历链表 A A A 的每个元素并存储到哈希表中;之后遍历链表 B B B 的每个元素进行查找。

  • 当前元素不在哈希表中,遍历下一个元素;
  • 当前元素在哈希表中,返回当前元素;
  • 如果链表 B B B 遍历结束,则两个链表不相交,返回 n u l l null null

代码

/**
 * 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*> hash;
        while(headA != nullptr) {
            hash.insert(headA);
            headA = headA->next;
        }
        while(headB != nullptr) {
            if(hash.count(headB)) 
                return headB;
            headB = headB->next;
        }
        return nullptr;
    }
};

复杂度分析

  • 时间复杂度: O ( m + n ) O(m+n) O(m+n),其中 m m m n n n 是链表 A A A B B B 的长度。哈希表可以在 O ( 1 ) O(1) O(1) 的时间进行查找。
  • 空间复杂度: O ( m ) O(m) O(m),需要使用哈希集合存储链表 链表 A A A 中的全部元素。

方法二:双指针

分析

假设链表 A A A B B B 存在交链长度 c c c,设链表 A A A 长度为 m = a + c m=a+c m=a+c 链表 B B B 长度为
n = b + c n=b+c n=b+c 使用指针 t e m p A tempA tempA 先遍历链表 A A A 后遍历链表 B B B;使用指针 t e m p B tempB tempB 先遍历链表 B B B 后遍历链表 A A A,指针 t e m p A tempA tempA 和指针 t e m p B tempB tempB 走过的路径长度为:
m + n = a + b + 2 c m+n=a+b+2c m+n=a+b+2c 由于链表 A A A B B B 存在交点,最后指针 t e m p A tempA tempA t e m p B tempB tempB 必然走了相同路径 c c c, 当指针 t e m p A = t e m p B tempA=tempB tempA=tempB 时,即指针 t e m p A tempA tempA t e m p B tempB tempB同时指向链表交点时,指针 t e m p A tempA tempA t e m p B tempB tempB 走过的路径长度为:
a + b + c a+b+c a+b+c 返回指针 t e m p A tempA tempA
特殊情况:当两个链表不相交时,即交链长度 c = 0 c=0 c=0,指针 t e m p A tempA tempA t e m p B tempB tempB 走过的路径长度为:
m + n = a + b m+n=a+b m+n=a+b 当指针 t e m p A = t e m p B tempA=tempB tempA=tempB 时,指针 t e m p A tempA tempA t e m p B tempB tempB同时指向 n u l l null null,返回 n u l l null null

代码

/**
 * 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 *tempA = headA, *tempB = headB;
        while(tempA != tempB) {
            tempA = tempA == nullptr ? headB : tempA->next;
            tempB = tempB == nullptr ? headA : tempB->next;
        }
        return tempA;
    }
};

复杂度分析

  • 时间复杂度: O ( m + n ) O(m+n) O(m+n),其中 m m m n n n 是链表 A A A B B B 的长度。
  • 空间复杂度: O ( 1 ) O(1) O(1)

拓展

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C每日一练中的环形链表Ⅱ问题是指LeetCode刷题专栏中的第142题。该问题的目标是找到给定链表中的环的入口节点。解决这个问题的一种常用方法是使用快慢指针。 快慢指针解法中,快指针的步数是慢指针的两倍,即慢指针一次走一步,快指针一次走两步。两个指针从链表的起始位置开始运行,如果链表中存在环,则快指针最终会追上慢指针,二者会在环中相遇。如果链表不带环,则快指针会率先走到链表的末尾。这种思路可以通过在纸上画图来更好地理解。 在解决环形链表Ⅱ问题时,我们可以按照以下步骤进行操作: 1. 定义快慢指针,初始时都指向链表的头节点。 2. 快指针一次走两步,慢指针一次走一步,直到两个指针相遇或快指针到达链表末尾。 3. 如果快指针到达链表末尾,则说明链表中没有环,直接返回null。 4. 如果快慢指针相遇,则说明链表中存在环。 5. 重新定义一个指针,从链表的头节点开始,与慢指针同时移动,每次移动一步,直到两个指针再次相遇。 6. 当两个指针再次相遇时,它们所指向的节点就是环的入口节点。 通过以上步骤,我们可以找到给定链表中环的入口节点。注意,在实际编码中,需要考虑边界条件和特殊情况的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【LeetCode】每日一题链表部分经典题型](https://blog.csdn.net/qq_63320529/article/details/130697933)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值