数据结构—单链表C语言刷题2

2023-11-06

目录

1.链表分割

2.链表的回文结构

3.相交链表

4.环形链表

5.环形链表II


1.链表分割

题目链接:链表分割

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

思路: 另外定义两个链表,遍历原链表的每一个节点,将节点中存储数据比x小的节点尾插到链表1后,将节点中存储的数据比大于等于x的节点尾插到链表2后,循环完后再将链表2的头尾插到链表1,这样就将两个链表链接为一个新的链表,最后返回链表1的头节点

实现:另外开辟两个哨兵位的头节点,链表1的头节点指针为lessHead,链表2的头节点指针为greaterHead,然后再定义两个链表的尾指针用来尾插,链表1的尾为lessTail,链表2的尾为greadterTail;定义结构体指针cur从原链表的头head开始遍历链表,比较cur->val与x的大小关系:若cur->val小于x则将cur对应的节点插入到链表1后,也就是将lessTail->next指向cur,然后cur继续向后走一步,lessTail也向后走一步;若cur->val大于等于x则相同的方法将cur尾插到链表2后;cur走到NULL时原链表遍历完了,结束循环 。之后将链表1链接到链表2后,这里需要注意:若倒数第二次循环判断的节点数据若大于等于x,则将该节点尾插到链表2后,greadterTail向后走一步之后指向该节点;最后一次循环判断的节点数据小于x,则将该节点尾插到链表2后,lessTail向后走一步指向该节点,然后循环结束了,greaterTail->next的值不会改变了,还是指向lessTail的,之后链接两个链表就会出现链表内成环的情况,链表2的尾节点指向链表1的尾结点,所以需要将greaterTail->next置成NULL最后定义一个结构体指针list用来保存新链表的头指针,用来返回;动态开辟的两个哨兵位节点需要free掉

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        struct ListNode* lessHead, *greaterHead, *lessTail, *greaterTail;
        lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));
        greaterHead  = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));
         
        lessTail->next = greaterTail->next = NULL;
        struct ListNode* cur = pHead;
        while(cur)
        {
            if(cur->val < x)
            {
                lessTail->next = cur;
                lessTail = cur;
                cur = cur->next;
            }
            else
            {
                greaterTail->next = cur;
                greaterTail = cur;
                cur = cur->next;
            }
        }
        lessTail->next = greaterHead->next;
        greaterTail->next = NULL;  //避免新链表中出现环
        struct ListNode* list = lessHead->next;
        free(lessHead);
        free(greaterHead);
        lessHead = NULL;
        greaterHead = NULL;
        return list;
    }
};

 2.链表的回文结构

题目链接:链表的回文结构

思路:先找到链表的中间节点,然后从中间节点处将之后的链表反转,再从链表的头节点和反转之后链表的中间节点开始比较两节点存储的数据,若不同则返回false,若相同则分别向后走继续判断;若循环结束了则返回true

实现:找链表的中间节点和反转链表在上一篇数据结构—单链表C语言刷题1中有题说明,这里直接引用这两个函数来实现相应的功能

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
//找到中间位置
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* cur = head;
    struct ListNode* newhead = NULL;
    while (cur)
    {
        struct ListNode* next = cur->next;
        cur->next = newhead;
        newhead = cur;
        cur = next;
    }
    return newhead;
}
 
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        ListNode* mid = middleNode(A);//先找到中间位置
        struct ListNode* mid1 = reverseList(mid);//从中间位置反转链表
         
        //从头和从中间反转之后的链表依次比较
        while(A && mid1)
        {
            if(A->val != mid1->val)
            {
                return false;
            }
            A = A->next;
            mid1 = mid1->next;
        }
        return true;
    }
};

3.相交链表

链接:相交链表

描述:

实现思路:分别遍历A链表和B链表,找到两个链表的尾节点,比较尾节点数据是否相等,相等则两链表相交,不相等则返回NULL。遍历的同时记录两个链表的节点数,用于找相交节点;若判断相交之后让较长的链表先走两个链表节点数的差值步,之后再一块走,走到存储数据相同的节点就是要找的相交节点

struct ListNode* tailA = headA, *tailB = headB;
    int LenA = 1, LenB = 1;
    //分别遍历A,B,并分别记录节点数
    while(tailA->next)
    {
        LenA++;
        tailA = tailA->next;
    }
    while(tailB->next)
    {
        LenB++;
        tailB = tailB->next;
    }
    //A,B遍历完之后比较最后一个节点是否相等
    if(tailA != tailB)
    {
        return NULL;
    }
    struct ListNode* shortlist = headA, *longlist = headB;
    if(LenA > LenB)
    {
        shortlist = headB;
        longlist = headA;
    }
    int differ = abs(LenA - LenB);
    
    //长的链表先走它们的差值
    while(differ--)
    {
        longlist = longlist->next;
    }
    //在一起走,节点相同的位置就是交点
    while(longlist && shortlist)
    {
        if(longlist == shortlist)
        {
            return longlist;
        }
        longlist = longlist->next;
        shortlist = shortlist->next;
    }
    //这里要注意,虽然前面已经全部判断完了,一定会有一个返回值,但是最后还需要返回一个值,否则会有编译错误
    return NULL;

 4.环形链表

链接:环形链表

描述:

思路:快慢指针:定义两个结构体指针fast和slow,fast和slow同时从原链表的头开始向后走,fast每次走两步,slow每次走一步;若链表不存在环,则fast走到空或者fast->next为空循环结束,返回false;若链表存在环,则fast比slow每次走快一步,fast先进入环,slow后进去环,slow进入环之后,fast开始追slow,当追到的时候,也就是fast和slow指向同一个节点的时候,返回ture

bool hasCycle(struct ListNode *head) {
    struct ListNode* slow = head, *fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {
            return true;
        }
    }
    return false;
}

只有slow一次走一步,fast一次走两步时,才一定能追上 。                                                                  证明:fast走的快先进环,进环之后fast就在环里面走,当slow进环的时候,假设此时slow和fast相差为N个节点,则之后每循环一次,fast和slow就的距离就减小1,此过程如:N,N-1,N-2,......  ,1,0,当距离缩小为0的时候fast就追上slow了

 slow一次走一步,fast一次三步时,不一定能追上。                                                                            证明:fast走的快先进环,进环之后fast就在环里面走,当slow进环的时候,假设此时slow和fast相差为N个节点,则之后每循环一次,fast和slow就的距离就减小2,当N是偶数时,此过程变为:N,N-2,N-4,...... ,2,0,则能追上;当N是奇数时,此过程变为:N,N-2,N-4,...... ,1,-1设环的长度为C,则此时fast和slow之间的距离为C-1,若C-1为偶数则如上分析fast能追上slow,若C-1为奇数,则永远也追不上了

slow一次走一步,fast一次走四步/五步等等,也是不一定能追上,同理分析

5.环形链表II

题目链接:环形链表II

描述:

这里的代码不是关键,而是需要证明一个关系公式。

设链表头到环入口点的距离为L,环入口点到fast与slow相交点的距离为X,环的长度为C;到fast与slow相遇点,slow走的距离为:L + X,fast走的距离为L + N*C + X,因为由于L和C大小差多少不确定,所以在slow进入环之前,fast可能走了很多圈也可能一圈也没走完,但是slow在进环之后的一圈内,fast一定能追上slow(slow进环之后fast和slow之间的距离最多为C-1);又由于fast走的距离是slow的二倍,就有如下关系:2 *(L + X) = L + N*C + X,化简为:L = N*C - X,也可以写成:L = (N - 1)*C + (C - X)方便理解。公式意思为:fast和slow的相遇点到环入口点的距离与链表头到环入口点的距离相等

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* slow = head, *fast = head;
    while(fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {
            struct ListNode* meet = slow;
            while(head != meet)
            {
                head = head->next;
                meet = meet->next;
            }
            return meet;
        }
    }
    return NULL;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构—单链表C语言刷题2 的相关文章

  • 算法题-简单系列-01-链表反转

    文章目录 1 题目 1 1 使用栈解决 1 2 反转链表 1 题目 给定一个单链表的头结点pHead 该头节点是有值的 比如在下图 它的val是1 长度为n 反转该链表后 返回新链表的表头 如当输入链表 1 2 3 时 经反转后 原链表变为
  • Radix Tree用法

    目录 一 radix tree定义 二 radix tree操作 参考资料 一 radix tree定义 对于长整型数据的映射 如何解决Hash冲突和Hash表大小的设计是一个很头疼的问题 radix树就是针对这种稀疏的长整型数据查找 能快
  • 算法设计与实现--动态规划篇

    什么是动态规划算法 动态规划算法是一种求解复杂问题的方法 通过将原问题分解为相对简单的子问题来求解 其基本思想是将待求解的问题分解为若干个子问题 阶段 按顺序求解子阶段 前一子问题的解 为后一子问题的求解提供了有用的信息 在求解任一子问题时
  • D (1173) : A DS二叉树_合并二叉树

    文章目录 一 题目描述 二 输入与输出 1 输入 2 输出 三 参考代码 一 题目描述 给定两个二叉树 输出这两个二叉树合并后形成的二叉树 依次输出前序遍历 中序遍历 后序遍历 二 输入与输出 1 输入 第一行输入t 表示有t个测试样例 第
  • 数组实现循环队列(增设队列大小size)

    目录 一 前言 1 如何实现循环 2 如何判断队列为空 3 如何判断队列为满 二 循环队列的结构定义 三 循环队列的创建及其初始化 四 入队 五 出队 六 取队头元素 七 取队尾元素 八 循环队列判空 九 循环队列判满 十 循环队列销毁 一
  • 不会做的题汇总

    摘苹果 题目描述 小红来到苹果园 帮园长摘苹果 园长请小红把摘完的苹果的最小的那个去掉 如果有 多个最小的苹果 那么都要去掉 剩余的苹果算一下平均一个苹果有多重 平均重 量请保留1位小数 输入 输入有2行 第一行 一个整数n代表小红摘的n个
  • 【数据结构入门精讲 | 第二篇】一文讲清算法复杂度

    上篇文章中我们引入了算法 数据结构 数据类型等概念 而要想衡量一个算法与数据结构是否为优质的 就需要一个衡量标准 这个衡量标准也是在我们实现一个好的算法时要遵循的原则 目录 基本概念 渐进性态 渐进性态数学表征 算法复杂度的运算 顺序搜索算
  • C语言之变量的存储方式和生存周期

    一 变量的存储方式 C语言变量的存储有两种方式 静态存储方式和动态存储方式 相应的生产期也有两种 静态生存期和自动生存期 静态存储方式 在程序运行前为变量内存分配内存 在程序结束后回收变量的内存 静态生存期 动态存储方式 在程序运行过程中
  • 剑指 Offer(第2版)面试题 35:复杂链表的复制

    剑指 Offer 第2版 面试题 35 复杂链表的复制 剑指 Offer 第2版 面试题 35 复杂链表的复制 解法1 模拟 剑指 Offer 第2版 面试题 35 复杂链表的复制 题目来源 48 复杂链表的复刻 解法1 模拟 算法 复制原
  • 深度学习目标检测全连接层什么意思

    在深度学习目标检测中 通常我们使用卷积神经网络 Convolutional Neural Network CNN 进行特征提取 CNN 的主要结构包括卷积层和池化层 用于从输入图像中提取特征 然而 为了最终输出目标的类别和位置信息 通常在网
  • 面试150-13(Leetcode238除自身以外数组的乘积)

    代码 class Solution public int productExceptSelf int nums int n nums length int res new int n int product 1 int zerocnt 0
  • 数组对象排序 (arr.sort())

    前端面试题库 面试必备 推荐 地址 前端面试题库 对象排序 arr sort 描述 方法sort 将在原数组上对 数组元素 进行排序 即排序时不创建新的数组副本 如果想按照别的顺序进行排序 就必须提供比较函数 该函数要比较两个值 然后返回一
  • 回溯算法第零篇【递归、搜索与回溯】【回溯算法入门必看】

    本篇文章的目的 1 给小伙伴们对回溯算法中的名词进行解释 2 消除递归的恐惧 回溯是递归的一个分支 给小伙伴们一个建议 整篇文章都要看完 一字不漏 全是干货 注意 分析回溯的思想之前 我们得知道一个关系 递归包含搜索 搜索包含回溯 所以我们
  • 【数据结构和算法】 K 和数对的最大数目

    其他系列文章导航 Java基础合集 数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一 题目描述 二 题解 2 1 方法一 双指针排序 三 代码 3 1 方法一 双指针排序 3
  • 代码随想录算法训练营第42天| ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集

    416 分割等和子集 已解答 中等 相关标签 相关企业 给你一个 只包含正整数 的 非空 数组 nums 请你判断是否可以将这个数组分割成两个子集 使得两个子集的元素和相等 示例 1 输入 nums 1 5 11 5 输出 true 解释
  • 【每日一题】2397. 被列覆盖的最多行数-2024.1.4

    题目 2397 被列覆盖的最多行数 给你一个下标从 0 开始 大小为 m x n 的二进制矩阵 matrix 另给你一个整数 numSelect 表示你必须从 matrix 中选择的 不同 列的数量 如果一行中所有的 1 都被你选中的列所覆
  • 排序:计数排序

    一 概念 计数排序是非比较排序 是对哈希直接定址法的变形应用 二 思想 利用数组统计相同数据出现的次数 例如整型数据m出现n次 就在数组m位置记录数据为n 最后从头遍历数组打印数据即可 通俗来讲就是 数组下标即为数据 下标所指位置的值即为数
  • 链表的中间节点

    链表的中间节点 力扣 LeetCode 官网 全球极客挚爱的技术成长平台 备战技术面试 力扣提供海量技术面试资源 帮助你高效提升编程技能 轻松拿下世界 IT 名企 Dream Offer https leetcode cn problems
  • 数据结构——排序

    前言 哈喽小伙伴们好久不见 也是顺利的考完试迎来了寒假 众所周知 不怕同学是学霸 就怕学霸放寒假 假期身为弯道超车的最佳时间 我们定然是不能懒散的度过 今天我们就一起来学习数据结构初阶的终章 七大排序 本文所有的排序演示都为升序排序 目录
  • 高精度运算合集,加减乘除,快速幂,详细代码,OJ链接

    文章目录 零 前言 一 加法 高精度加法步骤 P1601 A B 二 减法 高精度减法步骤

随机推荐

  • 显示等待和隐式等待

    学习显示等待和隐式等待使用 参考博客原址 https blog csdn net sinat 41774836 article details 88965281 文章目录 强制等待 sleep 隐式等待 implicitly wait 显示
  • 【Linux命令详解

    文章目录 简介 一 参数列表 二 使用介绍 1 修改用户权限 2 修改用户组权限 3 修改其他用户权限 4 同时修改多个权限 5 使用数字模式设置权限 6 递归修改目录权限 总结 简介 在Ubuntu系统中 chmod命令是一个强大的工具
  • 疯壳Android嵌入式Linux平板开发教程3-9G-sensor

    详情地址 https fengke club GeekMart views offline android 购买链接 https fengke club GeekMart su fHnaDyD1o jsp 视频地址 https fengke
  • c字符串分割成数组_leetcode第31双周赛第三题leetcode1525. 字符串的好分割数目

    leetcode1525 字符串的好分割数目 给你一个字符串 s 一个分割被称为 好分割 当它满足 将 s 分割成 2 个字符串 p 和 q 它们连接起来等于 s 且 p 和 q 中不同字符的数目相同 请你返回 s 中好分割的数目 示例 1
  • HCIP考试考哪三门你知道么?

    HCIP考试考哪三门 HCIP是华为认证中资深级别的认证 与hcia相比 它可能需要考多门考试 只有都通过了 才能获得HCIP认证 那么HCIP考试要考哪三门呢 其实 不同的方向需要通过的考试门数各不相同 有的只要通过一门 有的则是两门 最
  • kettle转换中文数据出现乱码

    在使用kettle转换数据时 有时会出现中文乱码问题 下面介绍解决办法 首先先保证你自己创建或连接的数据库是utf 8编码 1 设置DB连接 打开kettle中连接的数据库 在高级中输入set names utf8 2 再到选项中命名参数
  • Flink服务器无响应,apache-flink

    在这种情况下 我们有3个kafka主题 每个主题有50个分区 它们具有不同的消息 而所有这些消息都具有 用户名 字段 topic 1 gt Message01 String username about 50 000 messages pe
  • 分析Java线程池执行原理

    Java并发编程源码分析系列 分析Java线程池的创建 上一篇已经对线程池的创建进行了分析 了解线程池既有预设的模板 也提供多种参数支撑灵活的定制 本文将会围绕线程池的生命周期 分析线程池执行任务的过程 线程池状态 首先认识两个贯穿线程池代
  • Vue2.0 Vue脚手架 插件

    Vue当中有一个特别强大但写起来特别简单的一个东西 名字叫 插件 有什么作用 可以帮我们去增强一下Vue 先配置好项目 自己写的话 main js 项目执行npm run serve后第一个进入的 import Vue from vue i
  • maven报错‘has elapsed or updates are forced“

    使用 U强制更新参数运行maven命令
  • 少儿机器人编程有什么用

    少儿机器人编程有什么用 小孩的学习一直以来都是家长们非常关心和重视的一件事情 很多的家长在培养孩子的学习方面也可以说是相当的耐心的 会给孩子选择一些能更有利于孩子成长的课程 就拿现在很多的家长想要孩子去学习机器人编程的课程来说 有的家长对于
  • 解决Enter passphrase for key

    两种解决方案 提示 Permissions 0644 for ssh id rsa pub are too open 解决方法 使用chmod 0600 ssh id rsa pub更改将公钥权限改成 600 提示 Enter passph
  • Java中的静态变量&静态方法

    静态变量 静态方法 静态变量又叫做类变量 静态方法又被称为类方法 均被static修饰 未被static修饰的成员变量和方法分别被称为实例变量和实例方法 1 静态方法中不需要它所属类的任何实例就可以访问 所以在静态方法中不可以使用this关
  • Swift语法学习--运算符与流程控制

    文章目录 运算符 循环 条件 预处理器指令 运算符 普通的运算符加减乘除 与或非 三元运算我觉得没必要再赘述了 就记录一下我不熟悉的 循环 条件 预处理器指令
  • SQL Server 数据库中添加文件组和数据文件

    SQL Server 现有数据库中添加文件组和数据文件 use CURRENT DB 进入当前操作数据库 go alter database CURRENT DB add filegroup FG1 向CURRENT DB 数据库添加FG1
  • idea安装插件plugin(主要针对网络连接不上的情况)

    STEP1 ctrl alt s 打开settings STEP2 在输入框键入 Plugins STEP3 输入你想要的插件名称 我这边输入的是nodejs 因为最近在学 我这边是安装过的 所以这样显示 STEP4 点开中下方的前两个按钮
  • 在windows下编译glib库

    glib库是跨平台的C语言函数库 是Gtk 库和Gnome的基础 glib可以在多个平台下使用 比如Linux Unix Windows等 glib为许多标准的 常用的C语言结构提供了相应的替代物 先从官网下载下载 https downlo
  • Linux网络通信总结

    网络IO之阻塞 非阻塞 同步 异步 单播 多播 组播 广播 多路复用POLL SELECT epoll 超时 read write accept connect 超时 实现 1 用select来设置超时机制 2 使用setsockopt 函
  • React 子向父级组件通信时,state为旧的数据

    问题描述 当嵌套太深的子组件触发更新父组件时 父组件获取到的state map传入子组件 是旧的 问题场景 初始子组件仅为1个Input输入框 新增后有2个Input输入框 此时触发222输入框的修改 通知上级组件保存修改的内容时 父组件存
  • 数据结构—单链表C语言刷题2

    目录 1 链表分割 2 链表的回文结构 3 相交链表 4 环形链表 5 环形链表II 1 链表分割 题目链接 链表分割 题目描述 现有一链表的头指针 ListNode pHead 给一定值x 编写一段代码将所有小于x的结点排在其余结点之前