当前位置: 首页 > news >正文

数据结构(6)单链表算法题(下)

一、环形链表Ⅰ

1、题目描述

https://leetcode.cn/problems/linked-list-cycle

2、算法分析

思路:快慢指针 

根据上图所示的流程,我们可以推测出这样一个结论:若链表带环,快慢指针一定会相遇

那么,这个猜测是否正确呢?下面给出严格的证明——

证明1:在环形链表中,快慢指针为什么在环里一定会相遇?(慢指针每次走一步,快指针每次走两步)

以上面的图为例,假设slow刚入环,此时slow和fast之间的距离达到最大,最大值为N。接下来,slow前进一步,fast前进两步,此时两者距离变为N-1。同理,fast和slow再继续向后走,距离依次变为N-2,N-3……2,1,0 。当距离为0时,两指针相遇。

证明2:在环形链表中,慢指针每次走一步,但快指针每次走3/4/5/6……步,快慢指针在环里是否还会相遇?

假设慢指针每次走一步,快指针每次走三步。还是以刚才那副图为例,fast和slow之间的距离依次变为N-2,N-4,……如果N为偶数,那么最后距离变为4,2,0,快慢指针相遇。但是N为奇数的话,最后距离变为3,1,-1,距离变为-1时说明出现了套圈,也就是二者并没有相遇,此时二者之间的距离为C-1(假设环的周长为C)。那下一圈二者能否相遇呢?根据刚才的分析,当N为奇数的时候才会出现套圈的情况,若C-1为奇数,即C为偶数,一定不会相遇。若C-1为偶数,即C为奇数,下一圈一定会相遇。快指针走的总路程是慢指针的三倍,也就是3 * 慢指针 = 快指针。我们假设慢指针刚入环,快指针已经走了n圈,也就是慢指针当前走的总路程为L,快指针走的总路程为L+C-N+nC。带入公式得:3L = L + C - N + nC。化简得:2L = (n+1)C - N。等式左边的2L一定是偶数,根据数学知识可以知道:①偶数 - 偶数 = 偶数   ②奇数 - 奇数 = 偶数。所以我们得到下面的结论:C为奇数,N为奇数;C为偶数,N为偶数。但是我们先前又得到N为奇数,C为奇数一定会相遇;N为奇数,C为偶数一定不会相遇。所以C为偶数,N为奇数的情况不存在,既然不存在该情况,也就是说快指针一次走三步,最终也一定会相遇。同理,快指针每次走4、5、……步也是一样的道理。综上:快指针无论每次走多少步,快慢指针都可以在带环链表中相遇。但是在编写代码时会有额外程序步骤的引入,所以我们习惯上还是快指针走两步,慢指针走一步~

3、参考代码

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode *head) 
{//快慢指针ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast){//相遇return true;}}return false;
}

二、环形链表Ⅱ

1、题目描述

https://leetcode.cn/problems/linked-list-cycle-ii

2、算法分析 

思路:快慢指针

slow和fast相遇节点距离入环节点的距离为1,而头结点距离入环节点的距离也是1~

 

 slow和fast相遇节点距离入环节点的距离为0,而头结点距离入环节点的距离也是0~

 

 slow和fast相遇节点距离入环节点的距离为2,而头结点距离入环节点的距离也是2~ 

根据上面三个案例,我们可以作出猜想:快慢指针相遇点和头结点到入环起始节点的距离是相等的。下面给出严格的证明——

证明:为什么在带环链表中,快慢指针相遇点和头结点到入环第一个结点的距离相等?

快指针走的总路程是慢指针的两倍, 根据这句话,我们得到公式:2 * slow = fast。慢指针走过的总路程为L + X,快指针走过的总路程为L + X + nR。带入上述公式得:2(L + X) = L + X + nR。化简得:L + X = nR。即L = nR - X。变形一下得:L = (n-1)R + (R-X)。L是头结点到入环第一个结点的距离,R - X是相遇点到入环第一个结点的距离,(n-1)R是走过的完整的环的路程,对师资并没有影响,所以得到L = R - X,也就是快慢指针相遇点和头结点到入环第一个结点的距离相等。证明完毕~

3、参考代码

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) 
{//快慢指针ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(fast == slow){//找相遇点//相遇点和头结点到入环第一个节点的距离相等ListNode* pcur = head;while(pcur != slow){slow = slow->next;pcur = pcur->next;}//pcur == slowreturn pcur;}}return NULL;
}

三、链表分割

1、题目描述

2、算法分析 

思路:创建两个链表(小链表、大链表),遍历原链表,小的结点尾插到小链表中,大的节点尾插到大链表中,最后让大链表和小链表首尾相连。

3、参考代码

/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition
{
public:ListNode* partition(ListNode* pHead, int x){//创建两个带头的空链表ListNode* lessHead, *lessTail;lessHead = lessTail = (ListNode*)malloc(sizeof(ListNode));ListNode* greaterHead, *greaterTail;greaterHead = greaterTail = (ListNode*)malloc(sizeof(ListNode));ListNode* pcur = pHead;while(pcur){if(pcur->val < x){lessTail->next = pcur;lessTail = lessTail->next;}else{greaterTail->next = pcur;greaterTail = greaterTail->next;}pcur = pcur->next;}//大链表尾结点的next指针置为NULL(避免死循环)greaterTail->next = NULL;//大小链表首尾相连lessTail->next = greaterHead->next;ListNode* ret = lessHead->next;free(lessHead);free(greaterHead);lessHead = greaterHead = NULL;return ret;}	
};

http://www.dtcms.com/a/305191.html

相关文章:

  • 如何使用Spring AI框架开发mcp接口并发布成微服务
  • C51 中断
  • 笔试——Day22
  • 【Android】日期选择器
  • 镁金属接骨螺钉注册检测:骨科植入安全的科学基石
  • 【面试】软件测试面试题
  • ICT模拟零件测试方法--电阻测试
  • 集成电路学习:什么是WDT看门狗定时器
  • Java中的异常判断以及文件中的常用方法及功能
  • UCLAMP0501P.TCT SEMTECH:超低电容TVS二极管 0.25pF+20kV防护!
  • Python与Spark
  • 26考研11408数据结构
  • yolo11安卓端部署检测图片
  • Docker用Web应用实例深入容器
  • Docker初学者需要了解的几个知识点(三):Docker引擎与Docker Desktop
  • prometheus_client 调用统计
  • 2025年中科院与JCR期刊分区深度对比(第一期):TON中科院分区3区不变,JCR分区升至Q1;TOSEM重回中科院1区!
  • Wan2.1
  • openEuler性能测试常用工具-fio开源压力测试工具
  • 05动手学深度学习(下)
  • EnergyMath芯详科技 EMS4100/MES4000/MES3900
  • sqlite3---维护命令、回调函数
  • 用命令查看Android设备的 Linux 内核版本,了解其对应的硬件支持各种特性
  • gRPC性能陷阱:低延迟网络下的客户端瓶颈揭秘
  • k8s搭建nfs共享存储
  • 前端代码打包与压缩完全指南
  • div 封装日历
  • 使用echarts绘制立体柱状图
  • Export useForm doesn‘t exist in target module
  • 深度解读|美创科技参编国家标准《数字水印技术实现指南》