【链表OJ】相交链表 环形链表1

简介: 【链表OJ】相交链表 环形链表1

前言:

💥🎈个人主页:Dream_Chaser~ 🎈💥

✨✨刷题专栏:http://t.csdn.cn/UlvTc

⛳⛳本篇内容:力扣上链表OJ题目


一.leetcode 160. 相交链表


来源:160. 相交链表 - 力扣(LeetCode)


1.问题描述:

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回NULL 。

图示两个链表在节点c1开始相交

dc86934ff445486a9134824639d71d1f.png

已知a1与b1的头结点地址,并分别用headA和headB指针指向

  • 题目数据 保证 整个链式结构中不存在环。
  • 注意,函数返回结果后,链表必须 保持其原始结构

题目接口:

struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) 
{
}


2.解题思路:

原始链表:

00aaccfbf283423482f5f052dc1d841e.png

  • 首先定义tailAtailB分别遍历a链表b链表,在遍历过程中,分别求出两链表长度,分别定义为lenA和lenB,然后用lenA和lenB相减取差的绝对值,计为差距步gap

70067d4fcaff4eda9cff9f8a34dc9bed.png

然后定义指向长链表的指针longList,和指向短链表的指针shortList,用前面定义的LenA和LenB比较它们的长度,进行合适赋值,接着让长的链表走差距步gap。若长链表结点的地址不等于短链表,则让tailA和tailB指针继续走,有相等结点则跳出循环,返回此时的longList或者shortList。

4689ef286d914bd0ac82fd87fba642cd.png


实现代码:

struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) 
{
  struct ListNode* tailA = headA;
  struct ListNode* tailB = headB;
  int lenA = 1, lenB = 1;//原始长度定义为1才是正确的
    while (tailA)
    {
      tailA = tailA->next;
      lenA++;
    }
    while (tailB)
    {
      tailB = tailB->next;
      lenB++;
    }
    if (tailA != tailB)//若两指针到结束也找不到相等结点,则返回NULL
      return NULL;
    int gap = abs(lenA - lenB);//取出两者相减的绝对值,赋值给gap表示两链表的差距步
    struct ListNode*longList = headA;//先假定A链表为长链表
    struct ListNode* shortList = headB;
    if (lenA < lenB)//接着两链表比较,如果满足此条件,则重新赋值,定义B链表的为长链表
    {
      longList = headB;
      shortList = headA;
    }
  while (gap--)//长链表先走差距步
  {
    longList = longList->next;
  }
  while (longList != shortList)//若没有相等(地址相等)则继续遍历
  {
    longList = longList->next;
    shortList = shortList->next;
  }
  return shortList;
}


代码执行:

13ccca90e2c244b784fe0a4ff8120d03.png


二.leetcode 141.环形链表


1.问题描述:

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达则链表中存在环为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true。 否则,返回 false

3b96cccdc23643d38898595a5a97ac62.png

题解接口:

bool hasCycle(struct ListNode *head) {
}


2.代码思路:

本题的代码思路:

定义一个快指针,让其先走两步,接着定义一个慢指针,一次走一步,反复此循环。

  • 如果快慢指针指向的地址相等,则证明链表中存在环。
  • 如果快指针提前指向NULL,循环结束,则证明不是环形链表,直接返回false。


函数实现

bool hasCycle(struct ListNode *head) {
    struct ListNode* fast=head,*slow =head;
    while(fast && fast->next)
   {
     fast=fast->next->next;//快指针先走两步,慢指针走一步
     slow=slow->next; //慢指针走一步
    if(fast==slow)//指针相遇表明链表带环
    {
        return true;
    }
    }
    return false;//否则返回NULL
}


代码执行:

aaa8497dda2e4f8996d162eaf5ff8d97.png

然而本题的重点在于如何证明上面的代码的实现逻辑,是一个数学问题。


3.问题证明:


1、slow和fast一定会相遇吗?

答:一定会

画一张图来证明一下, 此时两指针同时指向头节点的地址。

2b78bee69f0c434688ca8c8054e7db31.png

接着先让快指针fast=fast->next->next(快指针先走两步),后让 slow=slow->next(慢指针走一步).

fast会先进环,slow会后进环,假设slow进环时,slow和fast之间的距离为N

c11da85911554aa59911783cc265cb75.png

slow进环以后,fast开始追击slow,slow每走1步,fast每走2步他们之间距离缩小1

9683c9d073b240c1ac8a8cfce01c67cd.png


2、slow走1步,fast走n(3/4/5….)步可以吗?(n > 2)

不一定


举例:

slow每次走步,fast每次走步,它们一定可以相遇吗?答:不一定。

画图

当快慢指针之间的距离个数为奇数

fast会先进环,slow会后进环,假设slow进环时, slow和fast之间的距离为N

slow进环以后,fast开始追击slow,slow每走1步,fast每走3步,他们之间距离缩小2

110f15b66d6e49168b04d3b2daadb120.png

当快指针追赶上慢指针时,此时错过了,并进入新一轮的追击,假设一个值C为环的长度,那么快慢指针的距离此时必为C-1

498cb07b41054ebba48610aebdc44b35.png

所以,如果C-1是奇数那么fast永远追不上slow

当C-1的距离为偶数时,那么此时的距离变化为

N N-2 N-4 ... 4 2 0 ,0则表示此时两指针相遇,表明下一轮可以追上。

     本文结束,如有错误,我会继续更新关于链表oj的题目,欢迎大家指正!

相关文章
|
2月前
|
存储 Java
数据结构第三篇【链表的相关知识点一及在线OJ习题】
数据结构第三篇【链表的相关知识点一及在线OJ习题】
29 7
|
2月前
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
18 1
|
2月前
【数据结构】环形、相交、回文、分割、合并、反转链表
【数据结构】环形、相交、回文、分割、合并、反转链表
30 0
|
5月前
【数据结构OJ题】复制带随机指针的链表
力扣题目——复制带随机指针的链表
55 1
【数据结构OJ题】复制带随机指针的链表
|
5月前
【数据结构OJ题】环形链表II
力扣题目——环形链表II
36 1
【数据结构OJ题】环形链表II
|
4月前
|
算法 Python
【Leetcode刷题Python】106.相交链表
采用双指针法来找出两个链表的相交起始节点,并详细解释了算法的时间和空间复杂度。
30 1
|
4月前
|
机器学习/深度学习
【刷题记录】相交链表
【刷题记录】相交链表
|
6月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
6月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表