【数据结构和算法初阶(C语言)】顺序表+单链表经典例题图文详解(题解大合集,搭配图文演示详解,一次吃饱吃好)

目录

 1.移除链表元素

1.1思路1:遍历删除 

1. 2  思路2:尾插法 

2.反转链表 

3.链表的中间节点 

 3.1解题思想及过程

3.2快慢指针思想解题---变式:返回链表的倒数第K个节点 

4.合并两个有序链表

4.1解题思想 1取小的尾插

5.反转链表

6、CM11 链表分割 (比较难)

描述

7.OR36 链表的回文结构

8.相交链表 

9.结语


 1.移除链表元素

1203. 移除链表元素icon-default.png?t=N7T8https://leetcode.cn/problems/remove-linked-list-elements/

 

1.1思路1:遍历删除 

struct ListNode* removeElements(struct ListNode* head, int val) {


if(head==NULL)
{
    return NULL;
}
 struct ListNode* cur = head;
struct ListNode* pre = head;

while(cur->next)
{
    if(cur->val==val)
    {
        //删除
        //如果是头结点
        if(head == cur)
        {
            head = cur->next;
            free(cur);
            cur = head;
            pre = cur;
            
        }
        else
        {
            pre->next = cur->next;
            free(cur);
            cur = pre->next;

        }
    }
    else 
    {
        pre= cur;
        cur = cur->next;
    }
   
}
//处理尾巴
if(cur->val == val)
{
    if(head == cur)
    {
        free(cur);
        return NULL;
    }
    else{
        pre->next = cur ->next;
        free(cur);
    }
}

return head;
}

1. 2  思路2:尾插法 

struct ListNode* removeElements(struct ListNode* head, int val) {


// if(head==NULL)
// {
//     return NULL;
// }
//  struct ListNode* cur = head;
// struct ListNode* pre = head;

// while(cur->next)
// {
//     if(cur->val==val)
//     {
//         //删除
//         //如果是头结点
//         if(head == cur)
//         {
//             head = cur->next;
//             free(cur);
//             cur = head;
//             pre = cur;
            
//         }
//         else
//         {
//             pre->next = cur->next;
//             free(cur);
//             cur = pre->next;

//         }
//     }
//     else 
//     {
//         pre= cur;
//         cur = cur->next;
//     }
   
// }
// //处理尾巴
// if(cur->val == val)
// {
//     if(head == cur)
//     {
//         free(cur);
//         return NULL;
//     }
//     else{
//         pre->next = cur ->next;
//         free(cur);
//     }
// }

// return head;


struct ListNode* cur = head;//用于遍历链表
struct ListNode* newhead = NULL;//创建新的头结点
struct ListNode* tail = NULL;//定义一个尾指针
//开始遍历原先的链表
while(cur)
{
    if(cur->val == val)
    {
        struct ListNode* deal = cur;//记录一下要删除的节点
        cur = cur->next;
        free(deal);
    }
    else 
    {
        if(tail == NULL)//第一次插入
        {
        tail = cur;
        newhead = cur;
        } 
        else 
        {
            tail ->next = cur;
            tail = tail ->next;
        }
        cur = cur->next;
    }
    //单独处理一下尾巴最后一个节点要删除的话,我们的这个尾节点要为空
    if(tail)
    {
        tail->next = NULL;
    }
    
}
return newhead;




}

 

2.反转链表 

206. 反转链表icon-default.png?t=N7T8https://leetcode.cn/problems/reverse-linked-list/ 放在第五讲解

3.链表的中间节点 

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/middle-of-the-linked-list/

 3.1解题思想及过程

这道题最简单的方法就是两次遍历的方法,第一次遍历就可以得到链表的长度,从而求得链表的的中间位置,第二次遍历返回中间节点就好。今天重点讲解一次遍历方法使用快慢指针

偶数长度的链表遍历结束的条件是:快指针指向空

奇数链表长度的遍历结束的条件是:快指针指向的下一个位置为空 

struct ListNode* middleNode(struct ListNode* head) {
    //快慢指针
     struct ListNode*  slow = head;
    struct ListNode*  fast = head;
    if(head == NULL)//传入空指针
    {
        return NULL;
    }
   
   
    while(fast&&fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;

    
    
}

 

3.2快慢指针思想解题---变式:返回链表的倒数第K个节点 

解题思想:快慢指针

快指针先走K步,然后和慢指针一起移动,直到快指针来到尾节点的下一个位置过后,慢指针指向的位置就是我们的倒数第k个节点。

特别注意就是:如果我们传入空链表或者我们的输入的倒数第几个的数据,但是链表没有那么长的时候,应该返回空。 

struct ListNode* FindKthToTail(struct Listnode* plistHead, int k)
{
	//首先判断一下链表为不为空,为空就返回NULL
	if (plistHead == NULL)
	{
		return NULL;
	}
	struct ListNode* slow, * fast;
	slow = fast = plistHead;

	//先让快指针走K步
	while (k--)
	{
		//但是要注意判断如果我们的链表没有K步长,就返回空
		if (fast == NULL)
		{
			return NULL;
		}
		fast = fast->next;
	}
	//然后快慢指针一起走,直到快指针走到空
	while (fast)
	{
		slow = slow->next;
		fast = fast->next;
	}
	return slow;
}

 

4.合并两个有序链表

21. 合并两个有序链表

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

4.1解题思想 1取小的尾插

主要是尾插思想,由于是有序链表,我们就取小的尾差到新的头结点,当一个链表或者两个链表同时走完就结束,将另外一个链表剩下的所有元素尾插到新的链表中然后返回头结点就可以。为了不增加遍历的时间复杂度,还是定义一个尾指针。

 

当有一个链表先走完时:
 

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    
    struct ListNode* head = NULL;//定义一个头指针
    struct ListNode* tail = NULL;//定义一个尾指针
    //先判断传入的链表中1是否有空链表,有就返回另外一个
    if(list1 == NULL)
    {
        return list2;
    }
    if(list2==NULL)

    {
        return list1;
    }
    while(list1 && list2)
    {
        if(list1->val< list2->val)//取小的尾插
        {
            if(tail == NULL)//判断是否是第一次插入
            {
                tail = head = list1;
                list1 = list1->next;
            }
            else
            {
                tail->next= list1;
               
               list1 = list1->next;
                tail = tail->next;
                
            }

        }
        else
        {
            if(tail == NULL)//判断是否是第一次插入
            {
                tail = head = list2;
                list2 = list2->next;
            }
            else
            {
                tail->next= list2;
                tail = tail->next;
               list2 = list2->next;
                
            }
        }
    }
    //出循环有一个链表为空,就要判断一下是哪一个为空,然后将另外一个进行尾插
    if(list1)
    {
        tail->next = list1;
    }
    if(list2)
    {
        tail->next = list2;
    }
    return head;
}

 

5.反转链表

. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。icon-default.png?t=N7T8https://leetcode.cn/problems/reverse-linked-list/ 

 

 解题思想:头插法

 

 

struct ListNode* reverseList(struct ListNode* head) {

//先判断一下传入的链表是否为空
if(head == NULL)
{
    return NULL;
}
    struct ListNode*  newhead = NULL;
    struct ListNode* cur = head;
    struct ListNode*  after=NULL;
    while(cur)
    {
        after = cur->next;
        cur ->next = newhead;
        newhead = cur;
        cur = after;
    }
    return newhead;
}

 

6、CM11 链表分割 (比较难)

描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

做题链接

补充带哨兵位的链表

 

首先解题的整体思想:
大于等于X的放置在一个链表,使用尾插的办法为了不改变顺序

小于X的放置在一个链表,也使用尾插的办法。

最后将两个链表链接起来。

这里使用带哨兵位的链表。我们先看一下代码实现,一边走一边说明问题

 

 

 

那么我们应该将大于数据的链表的尾巴置空。 

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here

        struct ListNode* lhead ,*ltail;//定义小于X的值存放的链表的头尾节点
        struct ListNode* ghead ,*gtail;//定义大于X的值存放的链表的头尾节点
        //申请哨兵位空间
        lhead = ltail = (  struct ListNode*)malloc(sizeof(  struct ListNode));
        ghead = gtail = (  struct ListNode*)malloc(sizeof(  struct ListNode));
        //开始循环遍历找
        struct ListNode* cur= pHead;
        while(cur)
        {
            if(cur->val <x)
            {
                ltail ->next = cur;
                ltail = ltail ->next;
                cur = cur->next;
            }
            else {
            gtail->next = cur;
            gtail = gtail->next;
            cur = cur->next;
            }
        }
        //链接
        ltail->next = ghead->next;
          gtail->next = NULL; 
        free(ghead);
        struct ListNode* head = lhead;
        head = head ->next;
        free(lhead);
      return head;

        
    }
};

7.OR36 链表的回文结构

题目地址

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。 给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。 测试样例: 1-2-2-1 返回:true



struct ListNode* reverseList(struct ListNode* head) {

	//先判断一下传入的链表是否为空
	if (head == NULL)
	{
		return NULL;
	}
	struct ListNode* newhead = NULL;
	struct ListNode* cur = head;
	struct ListNode* after = NULL;
	while (cur)
	{
		after = cur->next;
		cur->next = newhead;
		newhead = cur;
		cur = after;
	}
	return newhead;
}

struct ListNode* middleNode(struct ListNode* head) {
	//快慢指针
	struct ListNode* slow = head;
	struct ListNode* fast = head;
	if (head == NULL)//传入空指针
	{
		return NULL;
	}


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



}
bool chkPAlindrome(ListNode* head)
{
	struct ListNode* mid = middleNode(head);
	struct LIstNOde* rmid = reverselist(mid);
	while (rmid && head)
	{
		struct ListNode* scur = head;
		if(rmid->val != scur ->val)
		return false;

		rmid = rmid->next;
		
		scur = head->next;
	}
	
}

8.相交链表 

160. 相交链表

 

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

    struct ListNode * cura = headA,*curb = headB;
    int lena = 1;
    int lenb = 1;
    while(cura->next)
    {
        cura = cura->next;
        lena++;//计算链表a的长度
    }
      while(curb->next)
    {
        curb = curb->next;
        lenb++;//计算链表b的长度
    }
    //如果两个链表相交,那么尾结点的地址一定相等
    //所以这里就可以判断一下两个链表是否相交
    if(cura != curb)
    {
        return NULL;
    }
    int gap = abs(lena-lenb);//计算两个链表之间的差值,用来绝对值
    struct ListNode*longst = headA,*shortlist = headB;
    if(lena<lenb)
    {
        longst = headB;
        shortlist = headA;
    }
    while(gap--)
    {
        longst = longst->next;//长的先走差距步
    }
    //同时找交点
    while(longst != shortlist)
    {
        longst = longst->next;
        shortlist = shortlist->next;
    }
    return longst;
}

 

9.结语

今天关于简单链表的题目解析就更新到这里,下几篇内容是比较复杂的带环链表和复杂连边的题目,大家可以先收藏或者关注一波,方便链接后续新解 

 

 

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

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

相关文章

mindsdb,一个超酷的 Python 库!

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;今天为大家分享一个超酷的 Python 库 - mindsdb。 Github地址&#xff1a;https://github.com/mindsdb/mindsdb 在机器学习领域&#xff0c;构建和训练模型是一项复杂且耗时的任务。为了简化这个过程&#xff0c…

【C语言】linux内核generic_xdp_tx

一、中文注释 /* 在执行通用XDP时&#xff0c;我们必须绕过qdisc层和网络挖掘点&#xff0c;* 以匹配驱动内XDP的行为。*/ void generic_xdp_tx(struct sk_buff *skb, struct bpf_prog *xdp_prog) {struct net_device *dev skb->dev; // 获取skb对应的网络设备struct netd…

Stable-Diffusion ubuntu服务器部署,报错解决方法(小白教程)

Stable Diffusion是一个深度学习模型&#xff0c;专注于生成高质量的图像。它由CompVis团队与Stability AI合作开发&#xff0c;并在2022年公开发布。这个模型使用文本提示&#xff08;text prompts&#xff09;生成详细、逼真的图像&#xff0c;是目前人工智能图像生成领域的一…

Java中使用Jsoup实现网页内容爬取与Html内容解析并使用EasyExcel实现导出为Excel文件

场景 Pythont通过request以及BeautifulSoup爬取几千条情话&#xff1a; Pythont通过request以及BeautifulSoup爬取几千条情话_爬取情话-CSDN博客 Node-RED中使用html节点爬取HTML网页资料之爬取Node-RED的最新版本&#xff1a; Node-RED中使用html节点爬取HTML网页资料之爬…

C# aes加密解密byte数组

using System.Security.Cryptography; using System.Text;namespace AESStu01;public class AesHelper {// AES加密密钥和向量&#xff08;需要保密&#xff09; private static readonly string Key "";//16长度字符串数字混合private static readonly string IV …

Sqli-labs靶场第15关详解[Sqli-labs-less-15]

Sqli-labs-Less-15 #自动化注入-SQLmap工具注入 SQLmap用户手册&#xff1a;文档介绍 - sqlmap 用户手册 由于这题是post请求&#xff0c;所以先使用burp进行抓包&#xff0c;然后将数据包存入txt文件中打包 用-r 选择目标txt文件 python sqlmap.py -r data.txt -current-db…

对象变更记录objectlog工具(持续跟新)

文章目录 前言演示代码参考仓库 前言 对于重要的一些数据&#xff0c;我们需要记录一条记录的所有版本变化过程&#xff0c;做到持续追踪&#xff0c;为后续问题追踪提供思路。 演示代码 下面我们通过一段代码演示代码&#xff0c;展示如何自动将枚举字段&#xff0c;主键关…

VLAN实验报告

实验要求&#xff1a; 实验参考图&#xff1a; 实验过程&#xff1a; r1: [r1]int g 0/0/0.1 [r1-GigabitEthernet0/0/0.1]ip address 192.168.1.1 24 [r1-GigabitEthernet0/0/0.1]dot1q termination vid 2 [r1-GigabitEthernet0/0/0.1]arp broadcast enable [r1]int g 0/0/…

Github项目推荐-LightMirrors

项目地址 https://github.com/NoCLin/LightMirrors 项目简述 “LightMirrors是一个开源的缓存镜像站服务&#xff0c;用于加速软件包下载和镜像拉取。目前支持DockerHub、PyPI、PyTorch、NPM等镜像缓存服务。 当前项目仍处于早期阶段。”–来自项目说明。 也就是说&#xff…

持续集成(CICD)- Jenkins安装插件

文章目录 Jenkins 检查自己是否有此插件安装插件&#xff1a; 以Git 插件举例&#xff08;其他插件类似&#xff09;&#xff1a; Jenkins 检查自己是否有此插件 检查自己的jenkins是否有git插件&#xff1a;进入Manage Jenkins - 往下滑动找到Global Tool Configuration - 如…

在linux上不依赖于Nignx等服务器部署ASP.NET Core 7.0 WebAPI

笔者近期需要部署一款基于B/S架构的后端程序在linux的Debian发行版上&#xff0c;本文章以本次部署遇到的问题为线索&#xff0c;总结如何在Debian上部署ASP.NET Core7.0WebAPI应用程序。 在linux上不依赖于Nignx等服务器部署ASP.NET Core 7.0 WebAPI 1.先决条件2.应用发布3.部…

H12-821_108

108.路由器R1和R2分别使用GigabitEthernet0/0/0直连&#xff0c;并试图建立OSFP邻居&#xff0c;然而邻居关系并没有成功建立&#xff0c;排错过程如图所示。那么以下哪一个操作可以使R1和R2邻居管理正常建立&#xff1f; A. [R2] ospf 1 [R2-ospf-1]area 0 [R2-ospf-1-area-0.…

边缘计算网关的重要作用-天拓四方

随着物联网技术的迅猛发展&#xff0c;数据量的爆炸式增长对数据处理和分析提出了更高的要求。边缘计算网关作为连接物理世界和数字世界的桥梁&#xff0c;正逐渐受到各行业的重视。本文将从行业背景、功能特点以及带来的效益等方面&#xff0c;探讨边缘计算网关在当前及未来的…

政务信息化项目可行性研究报

第四章 总体建设方案 1 建设原则 本项目将在借鉴国内相关项目建设成功经验的基础上&#xff0c;充分利用现有先进、 成熟技术&#xff0c;并考虑长远发展需求&#xff0c;予以统一规划、统一布局、统一设计、规范标 准、突出重点、分步实施。 &#xff08;1&#xff09;标准…

【Datawhale组队学习:Sora原理与技术实战】AIGC技术基础知识

AIGC是什么 AIGC全称叫做AI generated content&#xff0c;AlGC (Al-Generated Content&#xff0c;人工智能生产内容)&#xff0c;是利用AlI自动生产内容的生产方式。 在传统的内容创作领域中&#xff0c;PGC&#xff08;Professionally-generated Content&#xff0c;专业生…

【论文阅读】Usenix Security 2023 你看不见我:对基于激光雷达的自动驾驶汽车驾驶框架的物理移除攻击

文章目录 一.论文信息二.论文内容1.摘要2.引言3.作者贡献4.主要图表5.结论 一.论文信息 论文题目&#xff1a; You Can’t See Me: Physical Removal Attacks on LiDAR-based Autonomous Vehicles Driving Frameworks&#xff08;你看不见我:对基于激光雷达的自动驾驶汽车驾驶…

如何将一个远程git的所有分支推到另一个远程分支上

如何将一个远程git的所有分支推到另一个远程分支上 最初有 12 个分支 执行 git remote add 远程名 远程git地址 git push 远程名 --tags "refs/remotes/origin/*:refs/heads/*"之后就变成 26个分支

基于springboot+vue的医院挂号就诊系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

自学也能高效备考2025年AMC8数学竞赛:2000-2024年AMC8真题解析

如何通过自学提高小学和初中数学成绩&#xff1f;现在小学和初中有哪些可以参加的数学竞赛&#xff1f;有没有难度适中、兼具趣味性的数学竞赛&#xff1f;现在参与人数较多的小学、初中数学有哪些&#xff1f;...如果你也在关注以上问题&#xff0c;不妨看看AMC8美国数学竞赛&…

Jmeter 安装

JMeter是Java的框架&#xff0c;因此在安装Jmeter前需要先安装JDK&#xff0c;此处安装以Windows版为例 1. 安装jdk&#xff1a;Java Downloads | Oracle 安装完成后设置环境变量 将环境变量JAVA_HOME设置为 C:\Program Files\Java\jdk1.7.0_25 在系统变量Path中添加 C:\Pro…