【LeetCode】【数据结构】单链表OJ常见题型(二)

news2025/1/12 12:06:22

 👀樊梓慕:个人主页

 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》

🌝每一个不曾起舞的日子,都是对生命的辜负


目录

前言:

【LeetCode】面试题02.04. 分割链表

【LeetCode】160. 相交链表

【LeetCode】141. 环形链表

【LeetCode】142. 环形链表Ⅱ

方法一

方法二 


前言:

本系列博文博主会讲解链表的经典OJ题目。

欢迎大家📂收藏📂以便未来做题时可以快速找到思路,巧妙的方法可以事半功倍。

=========================================================================

GITEE相关代码:🌟fanfei_c的仓库🌟

=========================================================================

【LeetCode】面试题02.04. 分割链表

原题链接:🍏分割链表🍏

题目:给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你不需要 保留 每个分区中各节点的初始相对位置。

本题使用带头结点的单链表更为简单,可以免去极端情况的判断(全大于等于x或全小于x)以及连接两个链表时的麻烦。

所以我们直接申请两个哨兵结点。

  • 令小于x的尾插到lead的链表上;
  • 令大于或等于x的尾插到ghead的链表上。

最后连接两个链表即可。

代码实现: 

struct ListNode* partition(struct ListNode* head, int x)
{
    struct ListNode* ghead,*gtail,*lhead,*ltail;
    struct ListNode* cur=head;

    ghead=gtail=(struct ListNode*)malloc(sizeof(struct ListNode));
    lhead=ltail=(struct ListNode*)malloc(sizeof(struct ListNode));

    while(cur)
    {
        if(cur->val<x)
        {
            ltail->next=cur;// 尾插
            ltail=ltail->next;
        }
        else
        {
            gtail->next=cur;// 尾插
            gtail=gtail->next;
        }
        cur=cur->next;
    }

    gtail->next=NULL;// 不置空 会导致链表进入循环

    ltail->next=ghead->next;// 连接两个链表

    struct ListNode* newhead=lhead->next;// 保存返回值,以便释放与返回
    free(lhead);
    free(ghead);

    return newhead;
}

【LeetCode】160. 相交链表

原题链接:🍏相交链表🍏

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

该题可以利用差距步的方法,首先计算两个链表的长度,利用该长度差让长的链表先走差距步。

再同时向后走,当两个指针相等时,该位置即为交点。

代码中的假设法是一种非常值得学习的方法,大家可以自行领悟,我在代码中标识出来了。

代码实现:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode* curA=headA;
    struct ListNode* curB=headB;

    int numA=1;
    int numB=1;
    while(curA->next)// 题目给定链表不为空,且两个循环结束后我们需要利用cur指针来判断是否相交,所以这里采用cur->next来判断结束
    {
        curA=curA->next;
        numA++;// 由于上面循环结束条件为cur->next为空,所以这里的值少1。因此我们定义num的值为1
    }

    while(curB->next)// 同上
    {
        curB=curB->next;
        numB++;// 同上
    }

    if(curA!=curB)// 不相交
    {
        return NULL;
    }

    struct ListNode* longList=headA,*shortList=headB;
    int gap=abs(numA-numB);// 计算差距步,abs绝对值函数
    if(numA<numB)// 假设法
    {
        longList=headB;
        shortList=headA;
    }

    while(gap--)// 令longList走差距步
    {
        longList=longList->next;
    }

    while(longList!=shortList)
    {
        longList=longList->next;
        shortList=shortList->next;
    }
    return longList;
}

【LeetCode】141. 环形链表

原题链接:🍏环形链表🍏

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

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

快慢指针法: 

定义两个指针。

  • 一个名为slow,slow每次走一步;
  • 一个名为fast,fast每次走两步。

当fast或者fast->next不为空时持续进行指针移动。

如果该链表为环形链表,那么一定存在某一时刻slow与fast相等,返回true;

如果跳出循环证明链表为非环形链表。

代码实现:

bool hasCycle(struct ListNode *head) 
{
    struct ListNode* slow=head;
    struct ListNode* fast=head;

    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
            return true;
    }
    return false;
}

 【LeetCode】142. 环形链表Ⅱ

原题链接:🍏环形链表Ⅱ🍏

题目:给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

方法一

与上面的思路相同,同样需要首先找到快慢指针相遇的时刻。

因为slow在一圈内必然fast会与其相遇,所以设slow在环内走了X距离。

设环外链表长度L,环的周长为C,slow进环时fast已经走了n圈,fast走的距离是slow走的距离的二倍,我们可以得到2(L+X)=L+n*C+X,即L=(n-1)*C+C-X。

如图:

结论:一个指针在相遇点meet,另一个指针为头指针,两指针同时移动,会在入环点相遇。

代码实现: 

struct ListNode* detectCycle(struct ListNode* head)
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;

    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            struct ListNode* meet = slow;
            while (head != meet)
            {
                meet = meet->next;
                head = head->next;
            }
            return head;
        }
    }
    return NULL;
}

 方法二 

还记得上面的题目相交链表么?

我们可以将该环在相遇点meet处断开,再执行判断相交链表的函数即可。

代码实现:

//相交链表
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{
    struct ListNode* curA = headA;
    struct ListNode* curB = headB;

    int numA = 1;
    int numB = 1;
    while (curA->next)// 题目给定链表不为空,且两个循环结束后我们需要利用cur指针来判断是否相交,所以这里采用cur->next来判断结束
    {
        curA = curA->next;
        numA++;// 由于上面循环结束条件为cur->next为空,所以这里的值少1。因此我们定义num的值为1
    }

    while (curB->next)// 同上
    {
        curB = curB->next;
        numB++;// 同上
    }

    if (curA != curB)// 不相交
    {
        return NULL;
    }

    struct ListNode* longList = headA, * shortList = headB;
    int gap = abs(numA - numB);// 计算差距步,abs绝对值函数
    if (numA < numB)// 假设法
    {
        longList = headB;
        shortList = headA;
    }

    while (gap--)// 令longList走差距步
    {
        longList = longList->next;
    }

    while (longList != shortList)
    {
        longList = longList->next;
        shortList = shortList->next;
    }
    return longList;
}

//环形链表Ⅱ
struct ListNode* detectCycle(struct ListNode* head)
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;

    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            struct ListNode* meet = slow;
            struct ListNode* newhead = meet->next;
            meet->next = NULL;

            return getIntersectionNode(head, newhead);
        }
    }
    return NULL;
}

快慢指针法是链表解题思路中非常常见的一种方法,博主在该系列博文的上一篇文章中也利用了该种方法,可以供大家整理参考,消化思路。

链接在这👉【LeetCode】【数据结构】单链表OJ常见题型(一)👈


=========================================================================

如果你对该系列文章有兴趣的话,欢迎持续关注博主动态,博主会持续输出优质内容

🍎博主很需要大家的支持,你的支持是我创作的不竭动力🍎

🌟~ 点赞收藏+关注 ~🌟

========================================================================= 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/830703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity实现物体上下漂浮旋转效果

效果展示 代码&#xff08;直接挂载在物体上就可以了&#xff09; using System.Collections; using System.Collections.Generic; using UnityEngine;public class FloatingObject : MonoBehaviour {public float amplitude 0.5f; // 上下移动的幅度public float frequency …

C# OpenCvSharp 去水印 图像修复

效果 项目 VS2010.net4.0OpenCvSharp3 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System…

简单了解一下vue-router是什么

要学习vue-router就要先知道这里的路由是什么&#xff1f;为什么我们不能像原来一样直接用<a></a>标签编写链接哪&#xff1f;vue-router如何使用&#xff1f;常见路由操作有哪些&#xff1f;等等这些问题&#xff0c;就是本篇要探讨的主要问题。 vue-router是什么…

【二叉树进阶】二叉树的前中后序遍历(非递归迭代实现)

文章目录 1. 二叉树的前序遍历1.1 思路分析1.2 AC代码 2. 二叉树的中序遍历2.1 思路分析2.2 AC代码 3. 二叉树的后序遍历3.1 思路13.2 思路1AC3.3 思路23.4 思路2AC 1. 二叉树的前序遍历 题目链接: link 不用递归&#xff0c;用迭代算法如何实现对二叉树的前序遍历&#xff1f…

linux作业

1.简述静态网页和动态网页的区别 (1).程序是否在服务器端运行&#xff0c;是重要标志。 (2).编程技术不同。静态网页和动态网页主要根据网页制作的语言来区分。 (3).被搜索引擎收录情况不同。 (4).用户访问速度不同。 (5).制作和后期维护工作量不同。 2. 简述 Webl.0 和 …

嵌入式pc技术的特点有哪些?

嵌入式PC技术是将计算机硬件和软件嵌入到各种设备中的一种技术&#xff0c;它具有低功耗、高效率、小型化、易于集成等优点&#xff0c;广泛应用于工业自动化、医疗设备、电力、通信、家用电器、物联网等领域&#xff0c;成为新时代工业生产和社会生活必不可少的技术之一。 嵌入…

Python基本数据类型之散列类型详解

前言&#xff1a; python的基本数据类型可以分为三类&#xff1a;数值类型、序列类型、散列类型&#xff0c;本文主要介绍散列类型。 一、散列类型 散列类型&#xff1a;内部元素无序&#xff0c;不能通过下标取值 1&#xff09;字典&#xff08;dict&#xff09;&#xff…

SAP 特殊采购类型52简介

特殊采购类型52简介-52 直接生产/收集订单可以在物料主数据中进行设置或者在BOM中进行设置, 所谓“直接生产”,是相对于一般的“间接生产”模式而言的。在我们通常采用的计划模式下面,所有在BOM结构里面的半成品,都是在库存中作为一个整体, 可以用在任意的一个成品物料,或…

STM32 NOR_FLASH 学习

NOR FLASH FLASH是常用的&#xff0c;用于存储数据的半导体器件&#xff0c;它具有容量大&#xff0c;可重复擦写、按“扇区/块”擦除、掉电后数据可继续保存的特性。 NOR FLASH的单位是MB&#xff0c;EEPROM的单位是KB。 NM25Q128&#xff0c;是NOR FLASH的一种&#xff0c…

正则匹配img标签里面src

正则&#xff1a; (?<src\s*\s*\")\S(?\"{1})匹配效果&#xff1a;

SAP F4下拉值报错:【内部错误:表格格式】

报错截图如下&#xff1a; 解决办法&#xff1a; 事务码&#xff1a;SU3 在【参数】页签维护如下值&#xff1a; SET/GET参数标识参数值简短描述F4METHODNoActiveXActiveX/NoActiveX 维护好以上信息之后&#xff0c;就可以正常显示下拉值了

OpenHarmony ArkUI 如何调用相机

​ ArkUI调用相机和调用相册其实是一个思路&#xff0c;只用修改一个地方。 我们继续来说相机调用&#xff0c;ArkUI没办法自己获取相机&#xff0c;所以得依靠一下ohos.multimedia.camera 相机开发指导 介绍 本指导主要展示了调用相机的调用过程&#xff0c;以及调用相机的…

【Elasticsearch】学好Elasticsearch系列-Query DSL

本文已收录至Github&#xff0c;推荐阅读 &#x1f449; Java随想录 先看后赞&#xff0c;养成习惯。 点赞收藏&#xff0c;人生辉煌。 文章目录 查询上下文相关度评分&#xff1a;_score源数据&#xff1a;_source数据源过滤器全文检索match&#xff1a;匹配包含某个term的子句…

整个个人博客?想找纯html代码模板?来个手机版带菜单的首页模板“参考参考”

以前做毕业设计的时候老想找一些不掺杂后端代码的前端模板。 可是下载下来&#xff0c;不是php就是python后台的。看又看不懂&#xff0c;想换语言就必须先把里面的后台代码拿掉。 就很像买了个精装的二手房&#xff0c;白白多花了砸墙钱。 就比如&#xff0c;想做个带菜单的…

【go-zero】docker镜像直接部署API与RPC服务 如何实现注册发现?docker network 实现 go-zero 注册发现

一、场景&问题 使用docker直接部署go-zero微服务会发现API无法找到RPC服务 1、API无法发现RPC服务 用docker直接部署 我们会发现API无法注册发现RPC服务 原因是我们缺少了docker的network网桥 2、系统内查看 RPC服务运行正常API服务启动,通过docker logs 查看日志还是未…

数据库相关知识点

体系结构图&#xff1a; 体系介绍&#xff1a; Client Connectors 接入方。支持很多协议(JDBC、ODBC、.NET、PHP、Python、PERL、C 等) Management Serveices & Utilities 系统管理和控制工具&#xff0c;mysqldump、 mysql复制集群、分区管理等 Connection Pool 连接池…

【css】css位置布局position

position 属性规定应用于元素的定位方法的类型。元素其实是通过使用top、bottom、left 和 right 属性来定位的。但是&#xff0c;需要首先设置了 position 属性&#xff0c;否则这些属性将不起作用。根据不同的 position 值&#xff0c;它们的设置特点不同。 其有五个不同的位…

【禅道】禅道数据迁移,源码安装的禅道18.2迁移至docker安装的禅道18.2

docker安装禅道开源版18.2 sudo docker run --name chandao \ -p 9080:80 \ -p 3306:3306 \ --networkzentaonet \ -v /opt/docker/zentao/zentaopms:/www/zentaopms \ -v /opt/docker/zentao/mysql:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD数据库密码\ -d easysoft/zentao:1…

Reset复位电路的PCB布局布线要求

Reset复位电路的PCB布局布线要求 —来源&#xff1a;瑞芯微RK3588 PCB设计白皮书 Reset复位电路是一种用来使电路恢复到起始状态的电路设计&#xff0c;一般简单的复位电路由电容串阻电阻构成&#xff0c;再复杂点就有三级管等配合进行&#xff0c;RK3588内置复位电路&#xf…

react中hooks分享

一. HOOKS是什么 在计算机程序设计中&#xff0c;钩子一词涵盖了一系列技术&#xff0c;这些技术用来通过拦截函数调用、消息或在软件组件之间传递的事件来改变或增加操作系统、应用程序或其他软件组件的行为。处理这些被截获的函数调用、事件或消息的代码称为“hook”。 在r…