[数据结构]链表OJ题 (三) 链表的中间结点、链表中倒数第k个结点、合并两个有序链表、链表分割、链表的回文结构

news2025/7/6 18:03:31

作者华丞臧.
专栏:【数据结构
各位读者老爷如果觉得博主写的不错,请诸位多多支持(点赞+收藏+关注)。如果有错误的地方,欢迎在评论区指出。
推荐一款刷题网站 👉 LeetCode刷题网站


文章目录

  • 一、链表的中间结点
    • 题目描述
    • 解题思路
    • 代码实现
  • 二、链表中倒数第k个结点
    • 题目描述
    • 解题思路
    • 代码实现
  • 三、合并两个有序链表
    • 题目描述
    • 解题思路
    • 代码实现
  • 四、链表分割
    • 题目描述
    • 解题思路
    • 代码实现
  • 五、链表的回文结构
    • 题目描述
    • 解题思路
    • 代码实现
  • 总结


一、链表的中间结点

题目描述

LeetCode.876 链表的中间结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。

在这里插入图片描述

解题思路

如果暴力求解,直接求链表长度再找中间结点程序过于繁琐,那么如何用更简单的方法求解呢?
快慢指针法:
既然题目要求链表中间结点,也就是说链表的 1/2 ;那么在一次遍历链表的过程中,给两个指针slowfast,slow一次走一步fast一次走两步fast遍历完链表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;
}

在这里插入图片描述

二、链表中倒数第k个结点

题目描述

牛客----链表中倒数第k个结点

输入一个链表,输出该链表中倒数第k个结点。

在这里插入图片描述

解题思路

输出链表中倒数第k个结点,经典快慢指针法的问题;定义一个slow指针一个fast指针,先让fast指针走指定的 k 步,然后再一起遍历链表,fast走完时slow的位置就是链表中倒数第k个结点

  1. k 小于链表的长度时
    假设 k = 1:
    在这里插入图片描述
  2. k 大于或等于链表的长度时
    需要注意,当k大于链表长度时,返回空指针;当 k 等于链表长度时,返回 slow
    在这里插入图片描述

代码实现

struct ListNode* FindKthToTail(struct ListNode* plisthead, int k ) {
    // write code here
    struct ListNode* fast = plisthead;
    struct ListNode* slow = plisthead;
   
    while(k-- )
    {
        if(fast == NULL)  //当k大于链表长度时
        {
            return NULL;
        }
        fast = fast->next;
    }

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

    return slow;
}

在这里插入图片描述

三、合并两个有序链表

题目描述

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

在这里插入图片描述

解题思路

创建一个新的链表头结点,依次比较传入的两个链表的大小,取其中的较小值尾插到新链表头结点后,并且让取出结点的那个链表的指针向后走一步再继续比较;循环此过程,当一个链表走到尾结束。
注意:当一个链表走完,另一个链表不一定走完,所以需要尾插剩下的那个链表。
在这里插入图片描述

代码实现

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode* cur1 = list1;
    struct ListNode* cur2 = list2;
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* cur = head;
    head->next = NULL;

    while(cur1 && cur2)
    {
        if(cur1->val < cur2->val)
        {
            cur->next = cur1;
            cur1 = cur1->next;
            cur = cur->next;
        }
        else
        {
            cur->next = cur2;
            cur2 = cur2->next;
            cur = cur->next;
        } 
    }

    if(cur1)
    {
        cur->next = cur1;
    }

    if(cur2)
    {
        cur->next = cur2;
    }

    cur = head->next;
    free(head);
    head = NULL;
    return cur;
}

在这里插入图片描述

四、链表分割

题目描述

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

解题思路

创建两个链表带头结点的链表 lessgreater ,遍历传入的链表,小于 x 的结点尾插到 less 链表 当中,大于 x 的结点尾插到 greater 链表当中;遍历完链表,把greater中的结点尾插到less链表即可
假设 x = 5:
在这里插入图片描述

代码实现

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        struct ListNode *less,*greater,*cur,*lesshead,*greaterhead;
        less = (struct ListNode*)malloc(sizeof(struct ListNode));
        greater = (struct ListNode*)malloc(sizeof(struct ListNode));
        lesshead = less;
        greaterhead = greater;
        cur = pHead;
         while(cur)
         {
             if(cur->val < x)
             {
                 less->next = cur;
                 less = less->next;
             }
             else
             {
                 greater->next = cur;
                 greater = greater->next;
             }
             cur = cur->next;
         }
         greater->next = NULL;
         less->next = greaterhead->next;
         less =  lesshead;
         greater = greaterhead;
         lesshead = lesshead->next;
         free(less);
         free(greater);
         less = greater = NULL;
         return lesshead;
    }
};

在这里插入图片描述

五、链表的回文结构

题目描述

牛客.OR36 链表的回文结构
对于一个链表,请设计一个时间复杂度为 O(n) ,额外空间复杂度为 O(1) 的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个 bool 值,代表其是否为回文结构。保证链表长度小于等于900

测试样例:
在这里插入图片描述

解题思路

在这里插入图片描述
通过上图可以看出,回文链表的前半段和后面的恰好相反,因为单向链表是单向的不能从链表两边往中间走;根据回文的特点,我们把后半段链表反转,然后一个指针从头部开始一个指针从链表尾部开始,依次比较其结点的值是否相等当两个指针中间没有元素时,则表示链表是回文结构。
注意:这种思路会破坏原先链表的结构
偶数项:
在这里插入图片描述
奇数项:
在这里插入图片描述

代码实现

struct ListNode* middleNode(struct ListNode* head)
    {
        struct ListNode* fast = head;
        struct ListNode* slow = head;
        while(fast && fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        return slow;
    }
    struct ListNode* reverseList(struct ListNode* head)
    {
        struct ListNode* cur = head;
        if(head == NULL )
        {
            return head;
        }
        else if(head->next == NULL)
        {
            return head;
        }
        struct ListNode* ptr = head->next;
        cur->next = NULL;
        while(ptr)
        {
            struct ListNode* tmp = ptr->next;
            ptr->next = cur;
            cur = ptr;
            ptr = tmp;
        }
        return cur;
    }

class PalindromeList {
     
public:
   
    bool chkPalindrome(ListNode* phead) {
        // write code here
        struct ListNode* cur = phead;
        struct ListNode* mid = middleNode(phead);
        struct ListNode* rmid = reverseList(mid);
        while(rmid)
        {
            if(cur->val != rmid->val)
            {
                return false;
            }
            cur = cur->next;
            rmid = rmid->next;
        }
        return true;
    }
};

在这里插入图片描述

总结

通过这些题目,学习了链表相关试题一些比较常用的方法:

  1. 双指针
  2. 快慢指针

并且在一些题目中,创建一个头结点可以很好地帮我们解决一些麻烦。

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

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

相关文章

Python学习笔记(十六)——Numpy

Numpy NumPy&#xff08;Numerical Python的简称&#xff09;是高性能科学计算和数据分析的基础包&#xff0c; 其中包含了数组对象(向量、矩阵、图像等)以及线性代数等。 NumPy库主要功能 • ndarray(数组)是具有矢量算术运算和复杂广播能力的多维数组。 • 具有用于对数组数…

项目资源管理从学会向上管理开始

“如何一句话证明你当过项目经理&#xff1f;” 这个话题在网上引发了广大项目管理人的兴趣&#xff0c;纷纷发表了个人看法&#xff08;变相吐槽&#xff09;。各种回答戳中笑点&#xff0c;同时也表达了作为项目经理的心酸。  “普通的薪资水平&#xff0c;却要为整个项目的…

基于微信公众平台API的菜谱小程序 的设计与实现

摘 要 由于人们生活水平的不断提高&#xff0c;人们对网络的需求也是不断提高&#xff0c;但是又不想通过下载各种不常用的app增加手机内存。小程序正好就可以做到这个特点&#xff0c;不用下载、及实际用、用完就走&#xff0c;现在很多的行业兴起&#xff0c;尤其餐饮行业最…

D. Decrease the Sum of Digits

Problem - 1409D - Codeforces 题意: 你得到了一个正整数n。在一次移动中&#xff0c;你可以使n增加1&#xff08;即使n:n1&#xff09;。你的任务是找出为了使n的数位之和小于或等于s&#xff0c;你需要执行的最小移动数。 你必须回答t个独立的测试案例。 输入 输入的第一…

基于最小二乘支持向量机(LS-SVM)进行分类、函数估计、时间序列预测和无监督学习(Matlab代码实现)

&#x1f4dd;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;…

Webpack基础使用 + 高级配置【重点!】

http://xxpromise.gitee.io/webpack5-docs/senior/optimizePerformance.html#code-split 笔记好评&#xff01;&#xff01;&#xff01;&#xff01;一定要把网址记好&#xff0c;真的nice&#xff01;&#xff01;&#xff01;&#xff01; 只是发博客记录一下&#xff0c;没…

java后端pageHelper分页实现方法

文章目录背景方法一&#xff1a;mysql的limit进行分页方法二&#xff1a;使用插件Mybatis-PageHelper(拦截器原理)1、本质2.实现步骤引入依赖修改application.yml修改代码总结背景 当一次查库数据量较大&#xff0c;不光给数据库带来压力&#xff0c;同时前端渲染页面压力也很…

Linux权限

系列文章目录 Linux 环境搭建以及xshell远程连接_crazy_xieyi的博客-CSDN博客 Linux常用命令详解_crazy_xieyi的博客-CSDN博客 文章目录 一、用户操作二、三种角色三、文件类型和访问权限四、修改文件权限一、用户操作 Linux下有两种用户&#xff1a;超级用户&#xff08;roo…

Java - SpringBoot整合Shiro之缓存功能

Java - SpringBoot整合Shiro之缓存功能前言一. SpringBoot 整合Redis1.1 配置 RedisTemplate1.2 Shiro整合Redis缓存配置1.3 测试前言 在 上一篇文章 主要讲了Shiro权限授权和认证跳过。本篇文章就主要讲解如何整合Shiro和Redis。这样就避免携带同一个Token的时候&#xff0c;…

百趣代谢组学文献分享:真假肥胖?代谢组说了算

肥胖是当今社会面临的很普遍的健康问题之一&#xff0c;超重会显著增加患糖尿病和心血管疾病的风险。而在日常生活中&#xff0c;我们发现有些肥胖者健康状况良好&#xff0c;而有些相对较瘦的人&#xff0c;却存在患糖尿病和心血管疾病的风险。 百趣代谢组学文献分享&#xf…

基于STM32结合CubeMX学习Free-RT-OS的源码之信号量与互斥量

目录 CUBEMX上的配置以及使用 信号量 互斥量 CUBEMX上的配置以及使用 信号量与互斥量都是从队列中衍生出来的&#xff0c;他们是一种特殊的队列。不同的地方在于:他们不含有队列的数据部分&#xff0c;只有队列结构体。 定义属性&#xff08;这里只有一个名字&#xff09;和…

Handler 消息队列中的同步屏障——Message

Message 分为3种&#xff1a;普通消息&#xff08;同步消息&#xff09;、屏障消息&#xff08;同步屏障&#xff09;和异步消息。我们通常使用的都是普通消息&#xff0c;而屏障消息就是在消息队列中插入一个屏障&#xff0c;在屏障之后的所有普通消息都会被挡着&#xff0c;不…

隐式类型转换(整形提升)

隐式类型转换1.定义2.整形提升例子3.char的取值范围和一些技巧1.定义 1.c的整形算术运算总是至少以缺省整形类型的精度来进行的。 2.为了获取这个精度&#xff0c;像字符型&#xff0c;短整形在使用之前会转换为整形&#xff0c;这种转换被称为整形提升 3.整形提升时补最高位的…

Baklib|信息管理和知识管理是如何影响你的业务的?

有效的信息和知识管理可以让您消除库和共享知识。本文讨论了信息管理和知识管理的来龙去脉。信息管理和知识管理通常可以互换使用&#xff0c;但也有关键的区别。了解这些差异以及它们如何影响您的业务&#xff0c;可以使您优化管理策略、简化工作流程并提高生产率。 本文涵盖…

灰色GM(1,1)模型及其在电力负荷预测中的应用附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

【每日一题】LFU 缓存

一个缓存结构需要实现如下功能&#xff1a; void set(int key,int value)&#xff1a;加入或者修改 key 对应的 value int get(int key)&#xff1a;查询 key 对应的 value 值 但是缓存最多放 K 条记录&#xff0c;如果新的 K 1 条记录需要加入&#xff0c;就需要根据策略删掉…

【面试题】如何替换项目中的if-else和switch

给大家推荐一个实用面试题库 1、前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 在项目中&#xff0c;往往会看到很多的if-else或者switch&#xff0c;项目会变得很臃肿&#xff0c;而且不易阅读&…

速溶颗粒:实验中的好伙伴

缓冲溶液 (buffer solution) 通常是由弱酸及其盐、弱碱及其盐组成的混合溶液&#xff0c;能在一定程度上抵消、减轻外加强酸或强碱对溶液酸碱度的影响&#xff0c;从而保持溶液的 pH 值相对稳定。 传统的缓冲液配制过程可简单概括为计算——称量——溶解——定容。而生物学上常…

windows10提权

参照tryhackme的win10提权靶场 靶场&#xff0c;地址 里面共描述了服务路径&#xff0c;文件权限&#xff0c;计划任务&#xff0c;令牌窃取&#xff0c;图形化软件&#xff0c;应用组件安装等&#xff0c;这里只有令牌窃取需要管理员Administrator权限&#xff0c;值得注意的是…

向毕业妥协系列之机器学习笔记:无监督学习-聚类

目录 序言 一.什么是聚类 二.K-means算法 三.优化目标 四.初始化K-means 五.选择聚类数量&#xff08;k?&#xff09; 序言 第三课这块要学习的几块知识如下&#xff1a; 在学完监督学习之后&#xff0c;接下来我们要学习的东西分别是聚类&#xff0c;异常检测&#xf…