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

 👀樊梓慕:个人主页

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

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


目录

前言:

【LeetCode】203.移除链表元素

【LeetCode】206.反转链表

 思路一

思路二

【LeetCode】876.链表的中间结点

快慢指针法

【LeetCode】剑指Offer 22.链表中倒数第k个结点

快慢指针法 

【LeetCode】21.合并两个有序链表

【LeetCode】剑指Offer Ⅱ 27.回文链表


前言:

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

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

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

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

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

【LeetCode】203.移除链表元素

原题链接:🍏移除链表元素🍏

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

 要想删除当前元素,需要知道当前元素的位置,及前一个元素的位置,并且保存下一个元素的位置。

所以我们需要三个指针:

  • 一个指针命名为cur,作用是遍历;
  • 一个指针命名为prev,指向位置为cur的前一个位置,作用是删除(prev->next=cur->next);
  • 一个next指针用来保存cur的后一个位置,确保free掉cur后仍然可以找到下一元素。

代码实现: 

/*
解题思路:从头节点开始进行元素删除,每删除一个元素,需要重新链接节点
*/
struct ListNode* removeElements(struct ListNode* head, int val) {
    if(head == NULL)
        return NULL;
    
    struct ListNode* cur = head;
    struct ListNode* prev = NULL;
    
    while(cur)
    {
        //如果当前节点是需要删除的节点
        if(cur->val == val)
        {
            //首先保存下一个节点
            struct ListNode* next = cur->next;
            //如果删除的为头节点,更新头节点
            //否则让当前节点的前趋节点链接next节点
            if(prev == NULL)
            {
                head = cur->next;
            }
            else
            {
                prev->next = cur->next;  
            }
            //释放当前节点,让cur指向next
            free(cur);
            cur = next;
        }
        else
        {
            //如果cur不是需要删除的节点,则更新prev,cur
            prev = cur;
            cur = cur->next;
        }
    }
    
    return head;
}

注意:考虑极端情况,如首个位置就是val的情况,作单独处理。


【LeetCode】206.反转链表

原题链接:🍏反转链表🍏

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

​ 

 思路一

同样的我们需要三个指针来完成这一操作:

  • 一个指针命名为cur,作用是遍历;
  • 一个指针命名为prev,作用是拿到cur的前一个地址,而后改变cur->next指向prev;
  • 一个指针命名为next,作用是保存cur的后一个位置,防止修改cur->next后找不到cur的后一个位置。

代码实现:

struct ListNode* reverseList(struct ListNode* head)
{
	struct ListNode* prev = NULL;
	struct ListNode* cur = head, * next = head;
	
	if (cur)// 检查cur是否为空
	{
		next = cur->next;
	}
	while (cur)
	{
        // 往后走
		prev = cur;
		cur = next;
		
        if(next)// 检查next是否为空
			next = next->next;
	}
	return prev;
}

思路二

取结点头插,完成逆置。

大家只要掌握了头插就很简单了。

代码实现:

// 取节点头插的思想完成逆置
struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode* newhead = NULL;
    struct ListNode* cur = head;
    while(cur)
    {
        struct ListNode* next = cur->next;
        //头插新节点,更新头
        cur->next = newhead;
        newhead = cur;
        cur = next;
    }
    
    return newhead;
}

【LeetCode】876.链表的中间结点

原题链接:🍏链表的中间结点🍏

题目:给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

快慢指针法

若想找到中间结点,我们可以定义两个指针:

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

这样当fast为NULL,或fast->next为NULL时,slow恰好处于中间位置,最后返回slow即可。

代码实现:

struct ListNode* middleNode(struct ListNode* head)
{
    struct ListNode* slow=head;
    struct ListNode* fast=head;
    while(fast && fast->next)// 分别为奇数个与偶数个的判断条件
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

【LeetCode】剑指Offer 22.链表中倒数第k个结点

原题链接:🍏链表中倒数第k个结点🍏

题目:输入一个链表,输出该链表中倒数第k个节点。

快慢指针法 

同样需要快慢指针的方法。

令fast先走k步,slow不动,然后slow与fast同时向后走,直到fast为NULL,此时slow的位置就是倒数第k个位置。

代码实现:

struct ListNode* getKthFromEnd(struct ListNode* head, int k)
{
    struct ListNode* slow=head,* fast=head;
    
    while(k--)
    {
        if(fast==NULL)
        {
            return NULL;
        }   
        fast=fast->next;
    }
    
    while(fast)
    {
        slow=slow->next;
        fast=fast->next;
    }
    
    return slow;
}

【LeetCode】21.合并两个有序链表

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

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

 思路:取小的尾插。

 注意:极端情况的判断,如其中一个链表为空等等。

代码实现: 

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1==NULL)// 判断其中一个链表为空的情况
    {
        return list2;
    }
    if(list2==NULL)// 判断其中一个链表为空的情况
    {
        return list1;
    }
    struct ListNode* head=NULL,*tail=NULL;
    while(list1 && list2)
    {
        if(list1->val<list2->val)
        {
            if(head==NULL)// 头结点直接赋值
            {
                head=tail=list1;
            }
            else// 尾插
            {
                tail->next=list1;
                tail=tail->next;
            }
            list1=list1->next;
        }
        else
        {
            if(head==NULL)// 头结点直接赋值
            {
                head=tail=list2;
            }
            else// 尾插
            {
                tail->next=list2;
                tail=tail->next;
            }
            list2=list2->next;
        }
    }
    if(list1)// list1有剩余
    {
        tail->next=list1;
    }
    if(list2)// list2有剩余
    {
        tail->next=list2;
    }
    return head;
}

【LeetCode】剑指Offer Ⅱ 27.回文链表

原题链接:🍏回文链表🍏

题目:给定一个链表的 头节点 head ,请判断其是否为回文链表。

如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

 思路:找到中间结点,将后半部分逆置,最后令前后两部分一一对比,如果结点的值全部相同,则为回文。

 刚好我们可以利用上面实现过的函数:链表的中间结点和反转链表。

代码实现:

// 找到中间结点
struct ListNode* middleNode(struct ListNode* head)
{
   struct ListNode* slow = head;
   struct ListNode* fast = head;
   while (fast && fast->next)
   {
       slow = slow->next;
       fast = fast->next->next;
   }
   return slow;
}

// 反转一个单链表
struct ListNode* reverseList(struct ListNode* head)
{
   struct ListNode* tail = NULL;
   struct ListNode* cur = head, * next = head;
   while (next)
   {
       next = cur->next;
       cur->next = tail;
       tail = cur;
       cur = next;
   }
   return tail;
}

// 判断回文结构
bool isPalindrome(struct ListNode* head)
{
    struct ListNode* mid=middleNode(head);
    struct ListNode* newhead=reverseList(mid);
    while(head && newhead)
    {
        if(head->val!=newhead->val)
        {
            return false;
        }
        else
        {
            head=head->next;
            newhead=newhead->next;
        }
    }
    return true;
}

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

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

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

🌟点赞收藏+关注 ~🌟

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

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

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

相关文章

SI24R2H 2.4G+125K中长跑应用原理

一、中长跑计时系统应用背景 采用125KHZ低频唤醒高频射频识别系统和先进的技术、计算机信息处理等高新技术与体育竞赛相结合&#xff0c;便于运动员携带而不影响其跑步状态&#xff0c;当运 动员带着射频识别卡经过计时线圈时&#xff0c;读卡天线能够立即检测到通过的卡片信息…

VR全景旅游,智慧文旅发展新趋势!

引言&#xff1a; VR全景旅游正在带领我们踏上一场全新的旅行体验。这种沉浸式的旅行方式&#xff0c;让我们可以足不出户&#xff0c;却又身临其境地感受世界各地的美景。 一&#xff0e;VR全景旅游是什么&#xff1f; VR全景旅游是一种借助虚拟现实技术&#xff0c;让用户…

【报错1】无法找到模块“element-plus/dist/locale/zh-cn.mjs”的声明文件。

报错&#xff1a;无法找到模块“element-plus/dist/locale/zh-cn.mjs”的声明文件。“e:/codeAll/webProject/Project/vue_ts/project727/node_modules/element-plus/dist/locale/zh-cn.mjs”隐式拥有 "any" 类型。 如果“element-plus”包实际公开了此模块&#x…

Charles安装和配置

Charles 是一个HTTP代理服务器,HTTP监视器,反转代理服务器&#xff0c;当程序连接Charles的代理访问互联网时&#xff0c;Charles可以监控这个程序发送和接收的所有数据。它允许一个开发者查看所有连接互联网的HTTP通信&#xff0c;这些包括request, response和HTTP headers &a…

快速响应,上门维修小程序让您享受无忧生活

随着科技的不断发展和智能手机的普及&#xff0c;上门维修小程序成为了现代人生活中越来越重要的一部分。上门维修小程序通过将维修服务与互联网相结合&#xff0c;为用户提供了更加便捷、高效的维修服务体验。下面将介绍上门维修小程序开发的优势。   提供便捷的预约方式&am…

OpenLayers入门,OpenLayers如何加载WFS服务的要素资源数据

专栏目录: OpenLayers入门教程汇总目录 前言 本章讲解如何使用OpenLayers加载WFS服务的要素资源数据。 WFS规范介绍 WFS是基于地理要素级别的数据共享和数据操作,WFS规范定义了若干基于地理要素(Feature)级别的数据操作接口,并以 HTTP 作为分布式计算平台。通过 WFS服…

.NET 8 Preview 5推出!

作者&#xff1a;Jiachen Jiang 排版&#xff1a;Alan Wang 我们很高兴与您分享 .NET 8 Preview 5 中的所有新功能和改进&#xff01;此版本是 Preview 4 版本的后续版本。在每月发布的版本中&#xff0c;您将看到更多新功能。.NET 6 和 7 用户可以密切关注此版本&#xff0c;而…

JVM总结笔记

JVM JVM是什么?JVM 的主要组成部分JVM工作流程JVM内存模型直接内存与堆内存的区别&#xff1a;堆栈的区别Java会存在内存泄漏吗&#xff1f;简述Java垃圾回收机制垃圾收集算法轻GC(Minor GC)和重GC(Full GC)新生代gc流程JVM优化与JVM调优 JVM是什么? JVM是Java Virtual Mach…

第五章 Opencv图像处理框架实战 5-3 图像阈值与平滑处理

图像阈值 ret, dst cv2.threshold(src, thresh, maxval, type) src&#xff1a; 输入图&#xff0c;只能输入单通道图像&#xff0c;通常来说为灰度图 dst&#xff1a; 输出图 thresh&#xff1a; 阈值 maxval&#xff1a; 当像素值超过了阈值&#xff08;或者小于阈值&am…

字符串性能优化

String 对象作为 Java 语言中重要的数据类型&#xff0c;是内存中占据空间最大的一个对象。高效地 使用字符串&#xff0c;可以提升系统的整体性能。 来一到题来引出这个话题 通过三种不同的方式创建了三个对象&#xff0c;再依次两两匹配&#xff0c;每组被匹配的两个对象是否…

分布式开源监控Zabbix实战

Zabbix作为一个分布式开源监控软件&#xff0c;在传统的监控领域有着先天的优势&#xff0c;具备灵活的数据采集、自定义的告警策略、丰富的图表展示以及高可用性和扩展性。本文简要介绍Zabbix的特性、整体架构和工作流程&#xff0c;以及安装部署的过程&#xff0c;并结合实战…

word里的页码问题

封面不需要页码怎么办 一份文档写完&#xff0c;如果需要页码&#xff0c;第一页是封面&#xff0c;封面不需要页码怎么办&#xff1f; 解决&#xff1a;打开页眉页脚&#xff0c;然后把首页不同勾选上&#xff0c;这一页就没有页码了。 目录页与正文页码格式不同怎么办 目录…

JIT 与 C#热更

JIT与AOT 一般程序运行有两种方式&#xff0c;静态编译与动态编译。 AOT: Ahead Of Time,预先&#xff08;静态&#xff09;编译 静态编译的程序&#xff0c;需要在执行之前全部翻译为机器码&#xff0c;运行前会使得程序安装时间相对较长&#xff0c;但程序运行的时候&#…

网络安全策略应包含哪些?

网络安全策略是保护组织免受网络威胁的关键措施。良好的网络安全策略可以确保数据和系统的保密性、完整性和可用性。以下是一个典型的网络安全策略应包含的几个重要方面&#xff1a; 1. 强化密码策略&#xff1a;采用强密码&#xff0c;要求定期更换密码&#xff0c;并使用多因…

【MySQL】mysql | linux | 离线安装mysqldump

一、说明 1、项目要求离线安装mysqldump 2、数据库服务已经使用docker进行安装&#xff0c;但是其他项目依赖mysqldump&#xff0c;所以需要在宿主机上安装mysqldum 二、解决方案 1、下载依赖 https://downloads.mysql.com/archives/community/ 2、下载内容 mysql-community-c…

【MyBatis】 框架原理

目录 10.3【MyBatis】 框架原理 10.3.1 【MyBatis】 整体架构 10.3.2 【MyBatis】 运行原理 10.4 【MyBatis】 核心组件的生命周期 10.4.1 SqlSessionFactoryBuilder 10.4.2 SqlSessionFactory 10.4.3 SqlSession 10.4.4 Mapper Instances 与 Hibernate 框架相比&#…

目标检测中 anchor base和anchor free

目标检测中两种不同anchor的生成 趋势&#xff1a;anchor free越来越受到实时性检测的青睐&#xff0c;&#xff0c;&#xff0c;

【LeetCode】不同路径Ⅱ

不同路径Ⅱ 题目描述算法流程编程代码 链接: 不同路径Ⅱ 题目描述 算法流程 编程代码 class Solution { public:int uniquePathsWithObstacles(vector<vector<int>>& ob) {int m ob.size();int n ob[0].size();vector<vector<int>>dp(m1,vecto…

Spring | Bean 作用域和生命周期

一、通过一个案例来看 Bean 作用域的问题 Spring 是用来读取和存储 Bean&#xff0c;因此在 Spring 中 Bean 是最核心的操作资源&#xff0c;所以接下来我们深入学习⼀下 Bean 对象 假设现在有⼀个公共的 Bean&#xff0c;提供给 A 用户和 B 用户使用&#xff0c;然而在使用的…

【嵌入式学习笔记】嵌入式入门2——中断(外部中断)

1.什么是中断 打断CPU执行正常的程序&#xff0c;转而处理紧急程序&#xff0c;然后返回原暂停的程序继续运行&#xff0c;就叫中断 1.1.中断的作用与意义 作用1&#xff1a;实时控制在确定时间内对相应事件作出响应——定时器中断作用2&#xff1a;故障处理检测到故障&…