数据结构——链表专题1

文章目录

  • 一、移除链表元素
  • 二、反转链表
  • 三、合并两个有序链表
  • 四、链表的中间节点
  • 五、环形链表的约瑟夫问题
  • 六、分割链表

一、移除链表元素

原题链接:移除链表元素

在这里插入图片描述

在这里插入图片描述

一个解法是遍历原链表,将与val相等的结点抛弃,链接后一个结点

在这里插入图片描述

另一个解法是创建一个新的链表,不保存与val相等的结点

在这里插入图片描述

注意:新的链表如果还没有插入结点,首先应该先将目的结点成为首结点
并且最后的尾结点的next应该置空

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* cur =  head;
    struct ListNode* phead = NULL;
    struct ListNode* ptail = NULL;
    while(cur)
    {
        if(cur->val != val)
        {
            //设置头结点
            if(phead == NULL)
            {
                phead = ptail = cur;
            }
            else
            {
                //尾插
                ptail->next = cur;
                ptail = ptail->next;
            }
        }
        cur = cur->next;
    }

    if(ptail)
    {
        ptail->next = NULL;
    }
    return phead;
}

二、反转链表

原题链接:反转链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一种解法是创建一个新的链表,遍历原链表,倒着储存进新的链表

另一个解法比较巧妙,需要三个指针
在这里插入图片描述

struct ListNode* reverseList(struct ListNode* head)
{
    if(head == NULL)
    {
        return head;
    }
    struct ListNode* n1 = NULL;
    struct ListNode* n2 = head;
    struct ListNode* n3 = head->next;
    while(n2)
    {
        n2->next = n1;
        n1 = n2;
        n2 = n3;
        if(n3)
        {
            n3 = n3->next;
        }
        
    }
    return n1;
}

三、合并两个有序链表

原题链接:合并两个有序链表

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
思路:创建一个新的链表,将上面两个链表遍历,将小的结点先储存在新的链表中
最后要么list1先遍历完,要么list2先遍历完,在写一个判断,将没有遍历完的链表的结点直接尾插到新的链表的末尾

注意:我们可以先创建一个哨兵位,方便我们直接插入数据,不在判断新的链表是否为空
在这里插入图片描述

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{

    if(list1 == NULL)
    {
        return list2;
    }

    if(list2 == NULL)
    {
        return list1;
    }
    //创建哨兵位
    struct ListNode* phead = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* ptail = phead;
    struct ListNode* pcur1 = list1;
    struct ListNode* pcur2 = list2;
    while(pcur1 && pcur2)
    {
        if(pcur1->val < pcur2->val)
        {
            ptail->next = pcur1;
            ptail = ptail->next;
            pcur1 = pcur1->next;
        }
        else
        {
            ptail->next = pcur2;
            ptail = ptail->next;
            pcur2 = pcur2->next;
        }
    }
    if(pcur1)
    {
        ptail->next = pcur1;
    }
    if(pcur2)
    {
        ptail->next = pcur2;
    }
    struct ListNode* ret = phead->next;
    free(phead);
    phead = NULL;
    return ret;
}

四、链表的中间节点

原题链接:链表的中间节点

在这里插入图片描述
在这里插入图片描述

使用快慢指针可以很好的解决这个问题
在这里插入图片描述

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}

五、环形链表的约瑟夫问题

原题链接:环形链表的约瑟夫问题
在这里插入图片描述
在这里插入图片描述
这个问题起源于一个故事:

著名的Josephus问题 据说著名犹太历史学家 Josephus有过以下的故事:在罗⻢⼈占领乔塔帕特后,39个犹太⼈与
Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被⼈抓到,于是决定了⼀个⾃杀
⽅式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3⼈该⼈就必须⾃杀,然后再由下⼀ 个重新报数,直到所有⼈都⾃杀⾝亡为⽌。
历史学家 然⽽Josephus和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与⾃⼰安排在
第16个与第31个位置,于是逃过了这场死亡游戏。

解决这道题,可以创建一个环形链表(循环链表),将题目的数据储存在链表的结点里面

在这里插入图片描述
然后创建两个指针,一个指向头结点,一个指向尾结点

在这里插入图片描述
如果满足条件,遇到要删除的结点,先将prev->next指向pcur->next,然后释放pcur结点,再将pcur结点往后移动一次

在这里插入图片描述
如果不满足条件,移动pcur和prev一次即可

注意:最后的循环结束条件是pcur->next = pcur,即只剩下一个结点,而不是pcur->next = prev,因为它们两个可能在移动中重合

在这里插入图片描述

//创建结点
struct ListNode* BuyNode(int x)
{
    struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
    if(newnode == NULL)
    {
        exit(1);
    }
    newnode->val = x;
    newnode->next = NULL;
    return newnode;
}
//创建环形链表
struct ListNode* CreatCirle(int n)
{
    struct ListNode* phead = BuyNode(1);
    struct ListNode* ptail = phead;
    for(int i = 2;i <= n;i++)
    {
        ptail->next = BuyNode(i);
        ptail = ptail->next;
    }
    //将尾结点和头结点连接起来
    ptail->next = phead;
    return ptail;
}
int ysf(int n, int m )
{
   int count = 1;
   struct ListNode* prev = CreatCirle(n);
   struct ListNode* pcur = prev->next;
   
   while(pcur->next != pcur)
   {
        if(count == m)
        {
            prev->next = pcur->next;
            free(pcur);
            pcur = prev->next;
            count = 1;
        }
        else
        {
            prev = pcur;
            pcur = pcur->next;
            count++;
        }
   }
   return pcur->val;
}

六、分割链表

原题链接:分割链表

在这里插入图片描述
在这里插入图片描述

解法一:创建两个新的链表,小的放在一起,大的放在一起,最后将小的链表后面合并上大的链表
解法二:在原链表的基础上,遍历链表,将小的位置不变,将大的尾插到链表的最后,删除前面的大的结点
解法三:创建一个新的链表,将小的结点头插,大的结点尾插

下面我们围绕解法一来解决这道题

在这里插入图片描述

为方便在新的链表里面插入结点,我们可以创建哨兵位,最后释放哨兵位就行了
注意:在合并后的链表里面,最后的结点的next一定要置为空并且它的位置在合并链表之前,因为大的链表如果没有结点,则只有一个哨兵位,没有next的指向,交换位置后会使用next指针导致出现错误

struct ListNode* partition(struct ListNode* head, int x)
{
    //空链表
    if(head == NULL)
    {
        return head;
    }

    //创建小的链表
    struct ListNode* lessnode = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* lesstail = lessnode;

    //创建大的链表
    struct ListNode* greaternode = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* greatertail = greaternode;

    //遍历链表
    struct 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 = greaternode->next;
    
    struct ListNode* phead = lessnode->next;
    //释放哨兵位
    free(lessnode);
    lessnode = NULL;
    free(greaternode);
    greaternode = NULL;
    return phead;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

corefBERT论文阅读

CorefBERT是清华大学团队发表的&#xff0c;继SpanBERT之后另一针对共指消解的BERT模型。共指消解任务对于文本理解、智能问答等其他NLP子任务起到至关重要的作用。 为了提高语言模型的共指推理能力&#xff0c;一个简单的解决方案是使用有监督的共指解析数据在bert等模型进行…

论文笔记ColdDTA:利用数据增强和基于注意力的特征融合进行药物靶标结合亲和力预测

ColdDTA发表在Computers in Biology and Medicine 的一篇一区文章 突出 • 数据增强和基于注意力的特征融合用于药物靶点结合亲和力预测。 • 与其他方法相比&#xff0c;它在 Davis、KIBA 和 BindingDB 数据集上显示出竞争性能。 • 可视化模型权重可以获得可解释的见解。 …

Linux网络部分——DNS域名解析服务

目录 1. 域名结构 2. 系统根据域名查找IP地址的过程 3.DNS域名解析方式 4.DNS域名解析的工作原理【☆】 5.域名解析查询方式 6.搭建主从DNS域名服务器 ①初始化操作主服务器和从服务器&#xff0c;安装BIND软件 ②修改主服务器的主配置文件、区域配置文件、区域数…

【c1】数据类型,运算符/循环,数组/指针,结构体,main参数,static/extern,typedef

文章目录 1.数据类型&#xff1a;编译器&#xff08;compiler&#xff09;与解释器&#xff08;interpreter&#xff09;&#xff0c;中文里的汉字和标点符号是两个字节&#xff0c;不能算一个字符&#xff08;单引号&#xff09;2.运算符/循环&#xff1a;sizeof/size_t3.数组…

基于java的CRM客户关系管理系统的设计与实现(论文 + 源码 )

【免费】基于Java的CRM客户关系管理系统的设计和实现.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89273409 基于Java的CRM客户关系管理系统的设计与实现 摘 要 随着互联网的高速发展&#xff0c;市场经济的信息化&#xff0c;让企业之间的竞争变得&#xff0…

复写零(双指针)

下面的解法需要手动画图&#xff0c;举例去体会&#xff0c;只有自己手动去做了&#xff0c;才会有所收获。 class Solution {public void duplicateZeros(int[] arr) {int n arr.length;//先找到最后一个元素的位置;//至于为什么要直接先设dest 为-1&#xff0c;这是经过研究…

CNN笔记详解

CNN(卷积神经网络) 计算机视觉&#xff0c;当你们听到这一概念的是否好奇计算机到底是怎样知道这个图片是什么的呢&#xff1f;为此提出了卷积神经网络&#xff0c;通过卷积神经网络&#xff0c;计算机就可以识别出图片中的特征&#xff0c;从而识别出图片中的物体。看到这里充…

分布式与一致性协议之ZAB协议(四)

ZAB协议 ZooKeeper是如何选举领导者的。 首先我们来看看ZooKeeper是如何实现成员身份的&#xff1f; 在ZooKeeper中&#xff0c;成员状态是在QuorumPeer.java中实现的&#xff0c;为枚举型变量 public enum ServerState { LOOKING, FOLLOWING, LEADING, OBSERVING }其实&…

为何美国多IP服务器是全自动内容采集站的最佳选择?

为何美国多IP服务器是全自动内容采集站的最佳选择? 在建设全自动内容采集站时&#xff0c;选择合适的服务器至关重要。而在众多选项中&#xff0c;美国多IP服务器被认为是最佳选择&#xff0c;究竟为何呢?本文将从多个方面进行深入探讨。 为何美国多IP服务器是全自动内容采集…

分享8000网剧资源

兄弟们&#xff0c;前段时间搞短剧&#xff0c;收集了8500多部网剧资源。搞了整整两个月就赚3块两毛八&#xff0c;电费都不够。还不如进厂打螺丝。果断放弃这项目。 资源在手里面也没啥用。分享出来&#xff0c;大家看着玩。 有其他好的网络项目也可以分享分享。也可也一起…

真希望我父母读过这本书的笔记(二)

系列文章目录 真希望我父母读过这本书的笔记&#xff08;一&#xff09; 真希望我父母读过这本书的笔记&#xff08;二&#xff09; 文章目录 系列文章目录PART 5 培养心理健康的孩子亲子关系决定心理健康互动及来回交流如何开始交流互看游戏交流恐惧症 若遇棘手之际&#xff0…

9.Admin后台系统

9. Admin后台系统 Admin后台系统也称为网站后台管理系统, 主要对网站的信息进行管理, 如文字, 图片, 影音和其他日常使用的文件的发布, 更新, 删除等操作, 也包括功能信息的统计和管理, 如用户信息, 订单信息和访客信息等. 简单来说, 它是对网站数据库和文件进行快速操作和管…

[Flutter]创建一个私有包并使用

在Flutter中创建一个自己的私有组件&#xff08;通常称为包或库&#xff09;&#xff0c;并通过Dart的包管理工具pub进行使用。 一、创建一个新的Flutter包 1.使用命令行创建 使用Flutter命令行工具来创建一个新的包&#xff1a; $ flutter create --templatepackage my_pri…

嵌入式复习重点

嵌入式系统有多种表现形式&#xff0c;包括计算机MCU、SOC片上系统、SOPC片上系统、GPU和FPGA等。 MCU(微控制器): 是最基本也是最常见的嵌入式系统形式,是集成了CPU、ROM、RAM、IO口、定时器、中断控制器等组件的单一芯片。MCU广泛用于电器电子产品的控制。SoC(系统片上芯片):…

P8800 [蓝桥杯 2022 国 B] 卡牌

P8800 [蓝桥杯 2022 国 B] 卡牌 分析 “最多” -- 二分 1.二分区间&#xff08;凑齐的卡牌套数&#xff09;&#xff1a; l&#xff1a;a[]min&#xff1b;r&#xff1a;(a[]b[])max 2.check(x)&#xff1a; &#xff08;1&#xff09;for循环内&#xff1a; 判断x - a[i…

Enhancing Diffusion——利用三维透视几何约束增强扩散模型

概述 透视在艺术中被广泛研究&#xff0c;但现代高质量图像生成方法却缺乏透视精度。新的生成模型引入了几何约束&#xff0c;通过训练过程提高透视精度。这样可以生成更逼真的图像&#xff0c;并提高相关深度估计模型的性能。 最近的图像生成技术使研究人员能够创造性地进行…

茅台葡萄酒打出节日新式营销“组合拳”,两月内落地品鉴会超千桌

执笔 | 尼 奥 编辑 | 古利特 2024年1-3月酒类进出口数据显示&#xff0c;葡萄酒进口量微增3.66%&#xff0c;进口额同比下滑11%&#xff0c;一季度整体跌势大缓&#xff0c;逐步走出普遍低迷的行情。与之相反的是&#xff0c;作为国产葡萄酒代表的茅台葡萄酒继续保持向上的战…

【C++】 认识多态 + 多态的构成条件详细讲解

前言 C 目录 1. 多态的概念2 多态的定义及实现2 .1 虚函数&#xff1a;2 .2 虚函数的重写&#xff1a;2 .2.1 虚函数重写的两个例外&#xff1a; 2 .3 多态的两个条件&#xff08;重点&#xff09;2 .4 析构函数为啥写成虚函数 3 新增的两个关键字3.1 final的使用&#xff1a;3…

线程详解(接上篇博客)

目录 1.生产者消费者模型; 2.基于环形队列的生产者消费者模型; 3.线程池; 4.STL, 智能指针, 线程安全; 5.读者写者问题. 前言: 本篇博客博主五一假期都在肝的一篇, 希望xdm点点三连, 博主感谢了 onz !!! 1.生产者消费者模型 321原则:(便于记忆) 3是指3种关系: 生产者和生产…

赚钱的背后逻辑!2024创业干什么最赚钱?2024创业方向!2024普通人的出路!2024普通人最有前景的行业!

钱根本不是赚来的。钱&#xff0c;是你帮别人解决问题后&#xff0c;对方给你的回报。什么时候把这句话理解透了&#xff0c;钱就会反过来追你。 问题就是每个人的痛点&#xff0c;痛点就是需求&#xff0c;男人怕穷&#xff0c;女人爱美&#xff0c;老人怕病&#xff0c;小孩怕…