单链表刷题(1-3)

news2024/11/19 10:40:52

目录

反转链表 

移除元素

合并有序链表


反转链表 

力扣

 我们用取头节点依次进行头插的方式解决这道题。需要注意的是头插前要保存下一个节点

struct ListNode* reverseList(struct ListNode* head){
    typedef struct ListNode SL;
    SL* cur = head;
    SL* rhead = NULL;//初始指向空
    while(cur)
    {
        SL* next = cur->next;
        cur->next = rhead;
        rhead = cur;
        cur = next;  
    }
    return rhead;
}

移除元素

力扣

思路一:删除第pos个位置的元素,也就是我们之前实现过的接口,需要考虑头删,以及是否传二级指针

思路二:根据上面的示范图,大家脑子里有没有形成一幅顺序表尾插添加数据的图,我们也可以取满足条件的数据进行尾插,忽略指定元素,并保留它的下一个元素。

 1.初始化指针

struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode SLT;
SLT* newhead = NULL,*tail = NULL;//新链表头和尾
SLT* cur = head;//原链表遍历指针

2.尾插  

while(cur)
{
    if(cur->val!=val)//不等
    {
    if(tail == NULL)//第一次
    {
        newhead = tail = cur;        
    }
    else
    {
        tail->next = cur;
        tail = tail->next;
    }
    cur =cur->next;
    else //相等
    {
        SLT* Next = cur->next;
        free(cur);
        cur = Next;
    }
}

整体逻辑是没问题的,但是却过不了测试用例

我们具体问题具体分析,既然不知道哪里错了,就自己勤快一点,写一个简单的单链表,来进行调试,这种方式能很好的提高我们解决问题的能力和提升我们的代码水平。

#pragma once
#include<stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef struct ListNode
{
    int val;
    struct ListNode* next;
}SLT;
SLT* CreateSList(int* a, int n)//用数组构建链表
{
    SLT* phead = nullptr, * ptail = nullptr;
    int x = 0;
    for (int i = 0; i < n; i++)
    {
        //sacnf("%d",&x);
        SLT* newnode = (SLT*)malloc(sizeof(SLT));//初始化(BuyList())
        if (newnode == nullptr)
        {
            perror("malloc fail");
            exit(-1);
        }
        else
        {
            newnode->val = a[i];
            newnode->next = nullptr;
        }
        if (phead == nullptr)//连结
        {
            phead = ptail = newnode;
        }
        else
        {
            ptail->next = newnode;
            ptail = newnode;
        }
    }
    return phead;
}

struct ListNode* removeElements(SLT* head, int val) {
    SLT* newhead = nullptr, * tail = nullptr;//新链表头和尾
    SLT* cur = head;//原链表遍历指针
    while (cur)
    {
        if (cur->val != val)//不等
        {
            if (tail == NULL)//第一次
            {
                newhead = tail = cur;
            }
            else
            {
                tail->next = cur;
                tail = tail->next;
            }
            cur = cur->next;
        }
        else //相等
        {
            SLT* Next = cur->next;
            free(cur);
            cur = Next;
        }
    }
    return newhead;
}
        int main()
        {
            int a[] = { 1,2,6,3,4,5,6};
            SLT* plist = CreateSList(a, sizeof(a) / sizeof(int));
            removeElements(plist, 6);
            return 0;
        }

大家能看出什么错误吗,没错,可以看到程序正常删除了我们想要的数据,但是最后一个数据没有指向空,而是指向了要删除的6的地址

解决了这个问题后更换力扣上的测试用例再调试,发现还有错:

这次的数组是每个都相同且均是删除对象,那这样就会导致tail指向空,发生解引用问题,所以我们再加上判断,这样就完美了。

struct ListNode* removeElements(SLT* head, int val) {
    typedef struct ListNode SLT;//最好不要这样定义
    SLT* newhead = nullptr, * tail = nullptr;//新链表头和尾
    SLT* cur = head;//原链表遍历指针
    while (cur)
    {
        if (cur->val != val)//不等
        {
            if (tail == NULL)//第一次
            {
                newhead = tail = cur;
            }
            else
            {
                tail->next = cur;
                tail = tail->next;
            }
            cur = cur->next;
        }
        else //相等
        {
            SLT* Next = cur->next;
            free(cur);
            cur = Next;
        }
    }
    if(tail)
    tail->next = nullptr;
    return newhead;
}

大家可以自己去实现一下我刚才的单链表调试函数,以后做题时遇到这种提醒就可以套模板调试,提升效率~。

这道题还可以添加哨兵节点做,这就有个好处:尾插进新链表时不用担心链表为空且省去了第一次尾插判空情况。


struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode SLT;
SLT* guard,*tail;
 guard = tail = (SLT*)malloc(sizeof(SLT));
SLT* cur = head;
while(cur)
{
    if(cur->val!=val)
    {
        tail->next = cur;
        tail = tail->next;
    cur =cur->next;
    }
    else 
    {
        SLT* Next = cur->next;
        free(cur);
        cur = Next;
    }
}
     tail->next = NULL;//避免删除最后一个数据前一个数据指向野指针
     SLT* newhead = guard->next;
     free(guard);
    return newhead;
}

注意返回时没有明确说明不能返回guard,而是返回它的下一个节点,也就是存储有效数据的节点。就算传递的是空指针也能有效返回。大家可以自行感受。

合并有序链表

力扣

思路:取小的尾插,其中一方结束就将剩余数据链接到新数组中去(有序)。

这里为了简单我们用哨兵节点实现。 

上面的测试用例表明如果其中一方为空或者都为空我们可以不用比较,直接返回他们的地址,这样就能完美通过了。

 

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    /*if(list1 == NULL)//非哨兵位
    {
        return list2;
    }
    if(list2 == NULL)
    {
        return list1;
    }*/
    struct ListNode* guard,*tail;
    guard = tail = (struct ListNode*)malloc(sizeof(struct ListNode));
    while(list1 && list2)
    {
        if(list1->val < list2->val)
        {
                tail->next = list1;
                tail = tail->next;
            list1 = list1->next;
        }
        else
        {
                tail->next = list2;
                tail = tail->next;
            list2 = list2->next;
        }
    }
if(list1)//剩余链接
    tail->next = list1;
if(list2)
    tail->next = list2;
    struct ListNode* newhead = guard->next;
    free(guard);
return newhead;
}

与上道题不同的是,这道题不用担心结尾节点野指针的问题。可以看到哨兵位十分方便。

总结一下:

  • 带哨兵位可以不用传递二级指针(只改变结构体)
  • 尾插用很方便
  • 单链表不常用

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

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

相关文章

TienChin 代码格式化-项目结构大改造

代码格式化 博主下载项目之后发现&#xff0c;整体的代码格式化风格&#xff0c;与 C 那种语言很相似&#xff0c;说明这个作者之前就是从事这块的导致风格有点类似&#xff0c;我们来格式化一下&#xff0c;当然这不是必要的&#xff0c;我是没习惯这种写法所以这里我写一下我…

2023年测试岗,你真的懂测试吗?凭什么他能月薪25k+

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试人员应该居安…

Redis入门 - 事务

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis入门 - 事务 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-transaction.html Redis 事务可以一次执行多个命令&#xff0c; 并且带有以下三个重要的保证&#xff1a; 批量操作在发送 EXEC 命…

STM32串口通信详解(嵌入式学习)

STM32串口通信 1.通信基础知识1.1 时钟信号区分同步通信异步通信波特率总线协议(电气协议) 1.2 通信方式划分串行通信并行通信 1.3 通信方向划分单工通信半双工通信全双工通信常见通信总结 2. USARTUSART 介绍 3. 串口通信协议4. 相关寄存器串口控制寄存器波特率寄存器中断和状…

segment anything环境配置与使用测试

硬件&#xff1a;RTX3070 i9-11900H 内存16G 目录 一、环境配置 二、使用测试--predictor_example.ipynb 1.jupyter notebook准备操作 2.Object masks from prompts with SAM与Environment Set-up 3.Set-up 4.Example image 5.Selecting objects with SAM 6.Specifyin…

GeoServer安装部署

GeoServer是一款开源的GIS服务器,用于管理、共享和编辑空间数据。 它的主要功能包括: 管理空间数据&#xff1a;GeoServer可以连接各种空间数据源,包括文件(SHP、CSV等)、数据库(PostGIS,Oracle,SQL Server等)和云存储(S3,Swift,Azure等)。并提供数据的浏览、上传、下载和删除…

webgpu之旅04

继续继续 319854902 319854902 319854902 319854902 webgpu交Q流群首先准备好绘制到屏幕所需的这个descriptor if rendertarget this._textures.initRenderTarget( renderTarget ); 来看一下这个函数里面会做什么 renderTargetProperties是这个target的properties 创建一个co…

历时一个月,腾讯认证python全套项目实战笔记,终于整理出来了

前言 之前拿到一份关于腾讯认证的python的全套项目实战脑图&#xff0c;于是历时花费一个月&#xff0c;终于是熬夜加点的给肝出来了&#xff0c;先用typora全部写出来&#xff0c;然后再导出成PDF文件&#xff0c;目前已经完全搞定。 总共划分内容为&#xff08;七大模块&am…

Telnet协议详解

Telnet协议是一种远程登录协议&#xff0c;它允许用户通过网络连接到远程主机并在远程主机上执行命令。本文将对Telnet协议进行详细介绍&#xff0c;包括其基本概念、连接方式、C/S模式以及工作原理。 一、Telnet协议的基本概念 1. NVT&#xff08;Network Virtual Terminal&a…

通付盾荣获第六届(2023)数字金融创新大赛“创新先锋榜”!

今日&#xff0c;第六届&#xff08;2023&#xff09;数字金融创新大赛“创新先锋榜”揭晓&#xff0c;大赛由中国电子银行网、数字金融联合宣传年主办&#xff0c;自4月6日开启以来&#xff0c;得到数字金融行业各方的积极响应与支持。经过专家评分、路演评审等环节&#xff0…

Android中Activity、View和Window关系详解

Android系统启动篇 1&#xff0c;《android系统启动流程简介》 2&#xff0c;《android init进程启动流程》 3&#xff0c;《android zygote进程启动流程》 4&#xff0c;《Android SystemServer进程启动流程》 5&#xff0c;《android launcher启动流程》 6&#xff0c;…

8年测试总结,App测试要点常见bug分类,从功能到性能测试...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 而针对手机应用软…

数字IC设计怎么入门?(附学习全流程)

看到很多小伙伴都不了解数字IC设计该怎么学&#xff0c;下面就来给大家来具体讲讲。 其实对于初级数字 IC 设计工程师而言&#xff0c;不仅仅需要较好的 Verilog 语法功底&#xff0c;还要熟悉企业的 Linux 环境以及 EDA 工具&#xff0c;此时你就需要掌握 Shell&#xff0c;V…

Django 权限管理和guardian插件

内置权限管理 Django内置的权限管理, 是一种表权限, 就是可分别配置某管理员用户对某个表的全部数据有没有增删改查4种权限. 图形界面配置权限 之前提到&#xff0c;使用命令行创建超管用户&#xff1a; python manage.py createsuperuser这其实是在最普通的用户的基础上将…

百度网盘的最新插件(懂得都懂)

下面先给大家介绍一下油猴插件。 这个插件为什么叫油猴&#xff1f; 现在我们经常提到的油猴插件&#xff0c;常指Tampermonkey&#xff0c;但Tampermonkey翻译过来是叫篡改猴&#xff0c;为什么会叫油猴呢&#xff1f;原因是因为另一个插件Greasemonkey&#xff0c;它翻译过…

Qt编写iFIx组态软件日报表插件的实现

一、iFIx中生成report.MDB文件 在Ifxi组态软件的【调度】中新建调度任务【report】添加【定时器调度项】FixTimer5&#xff0c;间隔1h触发一次。通过此任务及脚本程序&#xff0c;将相关变量定时存入自动生成的report.MDB文件中。 用户脚本程序如下&#xff1a; ---- User Co…

Sui对外开放开发者Office Hour

Sui宣布开启新一轮的Sui开发工程师Office Hour。本期的Office Hour由Sui基金会和Mysten Labs共同主办&#xff0c;为Sui上开发的相关技术问题进行答疑解惑并提供支持。 开发工程Office Hour将于每周五1:00 AM&#xff08;GMT8&#xff09;开设&#xff0c;时长为1小时。 每个…

程序性能优化实践总结——JAVA

文章目录 1、 衡量程序性能的指标2、Java 程序性能优化切入点3、获取程序的性能数据1、nmon:获取系统性能数据2、jvisualvm:获取JVM性能数据3、jmc:获取Java应用详细性能数据4、arthas:获取单个请求的调用链耗时5、wrk获取Web接口的性能数据 4、应用程序优化1、缓冲区2、缓存3、…

vm.min_free_kbytes调整导致GI异常,kernel: oracle: page allocation failure

有个11204 rac的测试环境&#xff0c;客户反馈凌晨rman全备时偶尔会有内存耗尽导致数据库重启的情况&#xff0c;不是合同内的维护环境&#xff0c;请我们帮忙处理。我估计是没配置vm.min_free_kbytes&#xff0c;之前也调整多次每次都成功完成&#xff0c;就没有多想&#xff…

ROS1 图像数据转发

为节约带宽提高效率采用jpeg: sensor_msgs::CompressedImage image_msg; ros::Publisher img_pub n.advertise<sensor_msgs::CompressedImage>(“image1”, 10); image_msg.format“jpeg” ; image_msg.data.resize(jpeg_data_size); memcpy(image_msg.data.data(),jpeg…