【数据结构】链表力扣刷题详解

news2025/2/24 21:33:43

前言

题目链接

移除链表元素

链表的中间结点

反转链表

分割链表

环形链表的约瑟夫问题


 

欢迎关注个人主页:逸狼


创造不易,可以点点赞吗~

如有错误,欢迎指出~


移除链表元素

题述

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 

思路1:直接删除原链表中不符合的节点

遍历原链表,遇到val就执行删除操作
执行删除操作修改指针的指向有点麻烦,还有其他办法

思路2:满足要求的节点放在新链表上

定义新链表,利用pcur遍历原链表,找不为val的节点,尾插在新链表中
新链表:newHead  newTail

要考虑链表是否为空
链表为空:插入进来的节点就是链表的头节点和尾节点
链表不为空,插入进来的节点就是链表的新的尾节点

代码实现思路2

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
    //定义新链表的头尾指针
    ListNode* newHead,* newTail;
    newHead=newTail=NULL;

    ListNode* pcur=head;
    while(pcur)
    {
        //不是val,尾插到新链表
        if(pcur->val!=val){
            //链表为空
            if(newHead==NULL)
            {
                newHead=newTail=pcur;
            }
            else{
                //链表不为空
                newTail->next=pcur;
                newTail=newTail->next;//
            }
        }
        //pcur继续往下走
        pcur=pcur->next;
    }
    if(newTail)//要先判断newTail本来是否为空
    {
        newTail->next=NULL;
    }
    return newHead;
}

链表的中间结点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点

思路1:统计链表中节点的个数,通过除2找到中间节点

for(统计链表个数)
    for(根据除2结果走到中间节点)

思路2:快慢指针

slow指针每次走1步,fast走2步
当fast->next或者fast走到为空,则slow刚好指向的就是中间节点
 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

 typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    ListNode* fast,*slow;
    fast=slow=head;
    while(fast&&fast->next)//条件fast和fast->next不能相反,会造成短路
    {
        slow=slow->next;//slow走1步
        fast=fast->next->next;//fast走2步
    }
    return slow;
}

 反转链表


给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

思路1

创建新链表,遍历原链表的节点将其插入到新链表中

思路2:创建3个指针

分别记录前驱节点,当前节点,后继节点,改变原链表的指向1

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
    //要先处理空链表
    if(head==NULL)
    {
        return head;
    }
    ListNode *n1,*n2,*n3;
    n1=NULL;
    n2=head;
    n3=head->next;

    while(n2)
    {
        //修改n2的指向
        n2->next=n1;
        //n1,n2,n3往下走
        n1=n2;
        n2=n3;
        if(n3)//要先判断n3不为空,才能往下走
        {
            n3=n3->next;
        }
    }
    return n1;
}

合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;

    ListNode *l1, *l2;
    l1 = list1, l2 = list2;
    //创建头节点
    ListNode *newHead, *newTail;
    newHead = newTail = (ListNode*)malloc(sizeof(ListNode));

    while (l1 && l2) {
        if (l1->val < l2->val) {
            // l1小,l1上,但要先判断l1不为空指针
            // if (newHead == NULL)
            //     newHead = newTail = l1;
            // else {
            //     newTail->next = l1;
            //     newTail = newTail->next;
            // }
            // l1 = l1->next;

            //代码优化
            newTail->next=l1;
            newTail=newTail->next;
            l1=l1->next;
        } else {
            // l2小
            // if (newHead == NULL)
            //     newHead = newTail = l2;
            // else {
            //     newTail->next = l2;
            //     newTail = newTail->next;
            // }
            // l2 = l2->next;

             //代码优化
            newTail->next=l2;
            newTail=newTail->next;
            l2=l2->next;
        }
    }
    if (l1) {
        newTail->next = l1;
    }
    if (l2) {
        newTail->next = l2;
    }
    return newHead->next;
}

分割链表


给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你不需要 保留 每个分区中各节点的初始相对位置。

思路

定义2个链表:大链表和小链表,遍历原链表的节点将其放到对应的新链表中,最将大小链表首尾相连

创建大小链表都要先创建一个哨兵位

利用pcur遍历链表

代码实现

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode; 
struct ListNode* partition(struct ListNode* head, int x){
    if(head==NULL)
        return head;
    //创建带头的大小链表
    ListNode* lessHead ,*lessTail;
    ListNode* greaterHead,*greaterTail;
    lessHead=lessTail=(ListNode*)malloc(sizeof(ListNode));
    greaterHead=greaterTail=(ListNode*)malloc(sizeof(ListNode));

    //遍历原链表,将节点放在对应的新链表中
    ListNode*pcur=head;
    while(pcur)
    {
        if(pcur->val < x)
        {
            //放在小链表中
            lessTail->next=pcur;
            lessTail=lessTail->next;
        }
        else
        {
            //放在大链表中
            greaterTail->next=pcur;
            greaterTail=greaterTail->next;
        }
    pcur=pcur->next;
    }
    //大链表尾要置为空
    greaterTail->next=NULL;

    //大小链表首尾相连
    lessTail->next=greaterHead->next;
    ListNode*ret=lessHead->next;
    free(greaterHead);
    free(lessHead);
    return ret;
}

环形链表的约瑟夫问题

编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。

下一个人继续从 1 开始报数。

n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?、

代码实现

 //这道OJ题已经创建好了结构体结点,只是没有展示出来
 typedef struct ListNode ListNode;
//申请新节点
ListNode* BuyNode(int x)
{
    ListNode* newNode=(ListNode*)malloc(sizeof(ListNode));
    //可写可不写,一般不会申请失败
    if(newNode==NULL)
    {
        exit(1);
    }
    newNode->val=x;
    newNode->next=NULL;
    return newNode;
}
//创建循环链表
ListNode*createList(int n)
{
    //创建头节点
    ListNode* phead=BuyNode(1);
    ListNode* ptail=phead;
    //从2开始,共创建了n个节点
    for(int i=2;i<=n;i++)
    {
        ptail->next=BuyNode(i);
        ptail=ptail->next;
    }
    //链表要首尾相连,循环起来
    ptail->next=phead;
    return phead;
}
int ysf(int n, int m ) {
    //创建不带头单向循环链表
    //逢m删除节点
    ListNode*head=createList(n);
    ListNode*pcur=head;
    ListNode*prev=NULL;//用于记录pcur走过的位置,是pcur的前驱节点

    int count=1;
    //逢m删除节点
    while(pcur->next!=pcur)//表示删除节点到只剩下自己跳出循环
    {
        if(count==m)
        {
            //删除当前节点pcur
            prev->next=pcur->next;
            free(pcur);
            //删除pcur节点后,要让pcur走到新的位置,count置为初始值
            pcur=prev->next;
            count=1;
        }
        else 
        {
            //pcur往后走
            prev=pcur;
            pcur=pcur->next;
            count++;
        }
    }
    //此时pcur节点就是幸存下来的节点
    return pcur->val;
}

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

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

相关文章

搜维尔科技:OptiTrack提供了一个通用、精确、灵活和可监控的系统!

MELS集成OptiTrack与最前沿的虚拟生产阶段 在加拿大蒙特利尔&#xff0c;MELS Studios and Postproduction设有20个工作室&#xff0c;以满足各种规模的电影和电视项目的需求。凭借先进的技术设施和专业的技术团队&#xff0c;梅尔斯为电影行业的合作伙伴提供从摄影棚和设备租…

应用开发技术巩固指南

前言 起初毕业前夕&#xff0c;个人已经开始自学Android开发&#xff0c;由于没有指导&#xff0c;所以起步很难&#xff0c;写的代码也规范&#xff0c;逻辑不清&#xff0c;技术止步于皮毛&#xff0c;很多东西都不理解。 后来步入工作&#xff0c;逐渐熟悉了这个方向&…

Zustand极简的状态管理工具

介绍 一个小型、快速且可扩展的 Bearbones 状态管理解决方案。 Zustand 有一个基于 hooks 的舒适 API。它不是样板文件或固执己见&#xff0c;但有足够的惯例来明确和类似通量。 zustand官网 zustand使用方法及调试工具的安装使用 安装包 npm install zustand2.创建store仓…

【算法专题--双指针算法】leetcode--283. 移动零、leetcode--1089. 复写零

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1. 移动零&#xff0…

多线程(部分)

Day28下2 多线程 一、什么是进程 进程是系统进行资源分配和调用的独立单元&#xff0c;每一个进程都有它的独立内存空间和系统资源。 二、单进程操作系统和多进程操作系统的区别 单进程操作系统&#xff1a;dos&#xff08;一瞬间只能执行一个任务&#xff09; 多进程单用户操…

想第一时间接收API变更信息?用Apipost这样做

Apipost致力于为开发者提供更全面的API管理功能。而最近&#xff0c;Apipost又新增了一个非常实用的功能&#xff1a;第三方消息推送。这个功能可以帮助开发人员及时了解API的变更情况&#xff0c;从而更好地管理和优化自己的API。 具体来说&#xff0c;Apipost的第三方消息推…

Linux操作系统——多线程

1.线程特性 1.1线程优点 创建一个新线程的代价要比创建一个新进程小得多与进程之间的切换相比&#xff0c;线程之间的切换需要操作系统做的工作要少很多线程占用的资源要比进程少很多能充分利用多处理器的可并行数量在等待慢速I/O操作结束的同时&#xff0c;程序可执行其他的计…

2024.3.9|第十五届蓝桥杯模拟赛(第三期)

2024.3.9|十五届蓝桥杯模拟赛&#xff08;第三期&#xff09; 第一题 第二题 第三题 第四题 第五题 第六题 第七题 第八题 第九题 第十题 心有猛虎&#xff0c;细嗅蔷薇。你好朋友&#xff0c;这里是锅巴的C\C学习笔记&#xff0c;常言道&#xff0c;不积跬步无以至千里&…

sql-bypass通关笔记(作业)

靶场环境的搭建&#xff1a; 首先安装dvwa靶场&#xff1b;因为要用到dvwa的数据库然后将该靶场放到phpstudy的www目录下创建一个网站指向该文件夹通过访问文件夹中php文件的形式进行闯关具体压缩包我放到最后的资料里了 index1.php通关笔记 知识点&#xff1a; 空格过滤 #…

51单片机—直流电机

1.元件介绍 2.驱动电路 3.电机调速 一般会保证一个周期的时间是一样的 应用&#xff1a; 1.LED呼吸灯 #include <REGX52.H>sbit LEDP2^0;void Delay(unsigned int t) {while(t--); } void main() {unsigned char Time,i;while(1){for(Time0;Time<100;Time){for(i0;…

MateBook 14s 2023款 集显 触屏(HKFG-16)原厂Win11系统

HUAWEI华为MateBook14s笔记本电脑2023款原装Windows11&#xff0c;恢复出厂开箱状态系统下载 适用型号&#xff1a;HKFG-XX、HKFG-16、HKFG-32 链接&#xff1a;https://pan.baidu.com/s/1GBPLwucRiIup539Ms2ue0w?pwdfm41 提取码&#xff1a;fm41 原厂系统自带所有驱动、…

python失物招领系统-安卓-flask-django-nodejs-php

对于本失物招领 的设计来说&#xff0c; 它是应用mysql数据库、安卓等技术动态编程以及数据库进行努力学习和大量实践&#xff0c;并运用到了 建设中在整个系统的设计当中&#xff0c;具体根据网上失物招领的现状来进行开发的&#xff0c;具体根据用户需求实现网上失物招领网络…

基于python的在线学习与推荐系统

技术&#xff1a;pythonmysqlvue 一、系统背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。这样的大…

【计算机视觉】三、图像处理——实验:图像去模糊和去噪、提取边缘特征

文章目录 0. 实验环境1. 理论基础1.1 滤波器&#xff08;卷积核&#xff09;1.2 PyTorch:卷积操作 2. 图像处理2.1 图像读取2.2 查看通道2.3 图像处理 3. 图像去模糊4. 图像去噪4.1 添加随机噪点4.2 图像去噪 0. 实验环境 本实验使用了PyTorch深度学习框架&#xff0c;相关操作…

STM32编写ADC功能,实现单路测量电压值(OLED显示)

先来看看本次实验的结果吧&#xff1a;stm32点电压测量范围为0-3.3V&#xff0c;数值为&#xff1a;0-4095 来看看这个工程的文件布局吧&#xff1a; 实现ADC功能总共分为六步&#xff1a; 第一步&#xff1a;开始RCC时钟&#xff0c;包括ADC和GPIO的时钟&#xff0c;ADCCLK的…

【Linux】——进程地址空间 Linux2.6内核进程调度队列

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 文章目录 前言 一、环境变量的补充 二、进程空间的地址 2.1、程序地址空间 2.2、研究背景 2.3、程序地址空间 来段代码感受一下 2.4、进程地址空间 2.5、如何…

【计算机网络】IP 协议

网络层IP协议 一、认识 IP 地址二、IP 协议报头格式三、网段划分1. 初识子网划分2. 理解子网划分3. 子网掩码4. 特殊的 IP 地址5. IP 地址的数量限制6. 私有 IP 地址和公网 IP 地址7. 理解全球网络&#xff08;1&#xff09;理解公网&#xff08;2&#xff09;理解私网&#xf…

一文搞懂IP

IP 1. 基本介绍2. IP地址定义3. IP地址分类4. 子网掩码5. 全局地址与私有地址 1. 基本介绍 TCP/IP 协议的心脏是网络层&#xff0c;主要“实现节点之间的通信”&#xff0c;即“点对点(end-to-end)通信”。 网络层包含IP(Internet Protocol)及DNS&#xff08;Domain Name Sys…

代码随想录算法训练营 DAY 14 | 二叉树的递归遍历和迭代遍历

二叉树基础 种类 满二叉树&#xff1a;深度为k&#xff0c;有2^k-1个节点的二叉树 完全二叉树&#xff1a;除了最底层可能没满&#xff0c;且都在靠左侧 优先级队列其实是一个堆&#xff0c;堆就是一棵完全二叉树&#xff0c;同时保证父子节点的顺序关系。 二叉搜索树&…

redis学习-String类型的命令介绍以及特殊情况分析

目录 1. set key value 2. get key 3. append key string 4. strlen key 5. incr key 和 decr key 6. incrby key num 和 decrby key num 7. getrange key start end 8. setrange key start string 9. setex key time value 10. setnx key value 11. mset key1 val…