【初阶数据结构】顺序表和链表算法题(下)

news2024/11/14 21:06:38

链表

  • 2.链表
    • 2.4合并两个有序链表
    • 2.5链表分割
    • 2.6链表的回⽂结构
    • 2.7相交链表
    • 2.8环形链表I
    • 2.9 环形链表II
    • 2.10随机链表的复制

2.链表

2.4合并两个有序链表

在这里插入图片描述
思路
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
    //处理链表为空的情况
    if (list1 == NULL)
        return list2;
    if (list2 == NULL)
        return list1;
    //方一代码:创建新的空链表
    ListNode* newhead = NULL, * newtail = NULL;
    //list1,list2分别指向两个链表的表头
    //newhead = newtail = (ListNode*)malloc(sizeof(ListNode));
    while (list1 && list2)//只要有一个条件不满足就跳出循环
    {
        if (list1->val < list2->val)
        {
            //谁小谁尾插
            if (newhead == NULL)
            {
                newhead = newtail = list1;
            }
            else
            {
                newtail->next = list1;
                newhead = newtail->next;
            }
            list1 = list1->next;
        }
        else
        {
            //l2尾插
            if (newhead == NULL)
            {
                newhead = newhead = list2;
            }
            else
            {
                newtail->next = list2;
                newtail = newtail->next;
            }
            list2 = list2->next;
        }
    }
    //跳出循环只有两种情况,list1为空或list2为空
    if (list1)
    {
        newtail->next = list1;
    }
    if (list2)
    {
        newtail->next = list2;
    }
    
    return newhead;
}
//方二代码:创建一个非空链表
typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    //申请一个动态的空间
    //此时初始了一个头结点,是个默认的值,最后删掉
    ListNode* newhead, * newtail;
    newhead = newtail = (ListNode*)malloc(sizeof(ListNode));
    while (list1 && list2)
    {
        //不用判断链表是否为空,直接拿过来尾插
        if (list1->val < list2->val)
        {
            newtail->next = list1;
            list1 = list1->next;
        }
        else
        {
            newtail->next = list2;
            list2 = list2->next;
        }
        newtail = newtail->next;
    }
    if (list1)
    {
        newtail->next = list1;
    }
    else
    {
        newtail->next = list2;
    }
    ListNode* ret = newhead->next;
    free(newhead);
    newhead = NUll;
    return ret;
}

2.5链表分割

在这里插入图片描述
思路
在这里插入图片描述

单链表算法题----链表分割
牛客是c++写的
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        if (pHead == NULL)
            return NULL;
        //创建两个非空链表,小链表和大
        struct ListNode* lessHead, * lessTail, * greaterHead, * greaterTail;
        //创建链表表头
        //注意:我动态开辟空间后 lesshead链表和greathead链表头就有一个默认结点啦
        lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));
        greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));
        //遍历原链表,找小于x的和其它节点尾插导大小链表中
        struct ListNode* cur = pHead;
        while (cur)
        {
            //小于x的尾插到lessTail
            if (cur->val < x)
            {
                lessTail->next = cur;
                lessTail = lessTail->next;
            }
            //大于等于x的尾插到greaterTail
            else
            {
                greaterTail->next = cur;
                greaterTail = greaterTail->next;
            }
            cur = cur->next;
        }
        //链接两个链表,小尾结点指向大的下一个结点
        lessTail->next = greaterHead->next;
        greaterTail->next = NULL;
        //获取表头
        pHead = lessHead->next;
        free(lessHead);
        free(greaterHead);
        return pHead;
    }
};

2.6链表的回⽂结构

在这里插入图片描述
思路
在这里插入图片描述

单链表算法题----链表的回⽂结构
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        // write code here
        if (A == NULL || A->next == NULL)
            return true;
        ListNode* slow, * fast, * prev, * cur, * nxt;
        slow = fast = A;
        //1.找到中间节点
        while (fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
        }
        //此时slow为中间结点 
        //后半部分逆置(反转链表)
        prev = NULL;
        cur = slow;
        while (cur)
        {
            nxt = cur->next;
            cur->next = prev;
            prev = cur;
            cur = nxt;
        }
        //逐点比对
        while (A && prev)
            //此时prev为最后一个结点
        {
            if (A->val != prev->val)
                return false;
            A = A->next;
            prev = prev->next;
        }
        return true;
    }
};

2.7相交链表

在这里插入图片描述
思路

在这里插入图片描述

单链表算法题----相交链表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
    typedef struct ListNode ListNode;
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) {
    ListNode* p1 = headA;
    ListNode* p2 = headB;
    int sizeA, sizeB;
    sizeA = sizeB = 0;
    while (p1) {
        sizeA++;
        p1 = p1->next;
    }
    while (p2) {
        sizeB++;
        p2 = p2->next;
    }
    //求绝对值
    int gap = abs(sizeA - sizeB);
    //让长链表先走gap步
    ListNode* longlist = headA;
    ListNode* shortlist = headB;
    if (sizeA < sizeB)
    {
        longlist = headB;
        shortlist = headA;
    }
    while (gap--)
    {
        longlist = longlist->next;
    }
    //此时,longlist和shortlist在同一起跑线
    //两种情况  相交,不相交
    while (longlist && shortlist)
    {
        if (longlist == shortlist)
        {
            //链表相交
            return shortlist;
        }
        //继续往后走
        longlist = longlist->next;
        shortlist = shortlist->next;
    }
    //都走到为空了,链表不相交
    return NULL;
}

在这里插入图片描述

2.8环形链表I

在这里插入图片描述
思路证明见下篇
在这里插入图片描述
在这里插入图片描述

单链表算法题----环形链表I
//判断是否带环
//判断是否相遇,环形链表2下个题是找相遇点
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
//走两步
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode* head) {
    //快慢指针
    ListNode* slow, * fast;
    slow = fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
        {
            return true;
        }
    }
    //两个指针始终没有相遇
    return false;
}
//走三步
typedef struct ListNode ListNode;
bool hasCycle(struct ListNode* head) {
    //快慢指针
    ListNode* slow, * fast;
    slow = fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        int n = 3;
        //fast每次⾛三步
        while (n--)//进去3次
        {
            if (fast->next)
                fast = fast->next;
            else
                //不带环
                return false;
        }
        if (slow == fast)
        {
            return true;
        }
    }
    //两个指针没有相遇
    return false;
}

2.9 环形链表II

在这里插入图片描述
结论
让⼀个指针(pcur)从链表起始位置开始遍历链表,同时让⼀个指针(next)从判环时相遇点(meet)的位置开始绕环运⾏,两个指针都是每次均走⼀步,最终肯定会在入口点的位置相遇。

第一步,找环的相遇点
第二步,从头结点和相遇点开始遍历,每次都走一步
第三步,当pcur和meet相遇时,即入口点

单链表算法题----环形链表II
//先运用找相遇点代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
ListNode* FindNode(ListNode* head)
{
    ListNode* fast, * slow;
    slow = fast = head;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast)
            return slow;//相遇了
    }
    return NULL;
}
struct ListNode* detectCycle(struct ListNode* head) {
    //找环的相遇点
    ListNode* meet = FindNode(head);
    //从头结点和相遇点开始遍历,每次都走一步
    ListNode* pcur = head;
    while (meet && pcur)
    {
        //当pcur和meet相遇时,即入口点
        if (meet == pcur)
            return meet;
        meet = meet->next;
        pcur = pcur->next;
    }
    //链表不带环
    return NULL;
}

2.10随机链表的复制

在这里插入图片描述
在这里插入图片描述
思路

第一步,在原链表基础上继续复制链表
第二步,置random指针,copy->random=pcur->random->next
第三步,复制链表与原链表断开
在这里插入图片描述
`

`附上几张图便于理解

在这里插入图片描述
第三步的时候 下图
在这里插入图片描述

单链表算法题----随机链表的复制
/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */
    typedef struct Node Node;
Node* BuyNode(int x)
{
    Node* newnode = (Node*)malloc(sizeof(Node));
    newnode->val = x;
    newnode->next = newnode->random = NULL;
    return newnode;
}
//原链表传过来,复制链表
void AddNode(Node* phead)
{
    Node* pcur = phead;
    while (pcur)
    {
        Node* ret = pcur->next;
        //创建新节点,尾插到pcur 
        Node* newnode = BuyNode(pcur->val);
        pcur->next = newnode;
        newnode->next = ret;
        pcur = ret;
    }
}
struct Node* copyRandomList(struct Node* head) {
    if (head == NULL)
        return NULL;
    //第一步
    AddNode(head);
    //第二步
    Node* copy, * pcur, * p1, * newhead, * newtail;
    pcur = head;
    newhead = newtail = pcur->next;
    p1 = pcur;
    while (pcur)
    {

        copy = pcur->next;
        if (pcur->random != NULL)
        {
            //如果为空,copy->random本来就是null,不用再改了
            copy->random = pcur->random->next;
        }
        pcur = copy->next;
    }
    //第三步
    //让pcur再回到头结点,所以有了p1
    while (p1->next->next)
    {
        p1 = p1->next->next;
        newtail->next = p1->next;
        newtail = newtail->next;
    }
    return newhead;
}
``


更多链表算法刷题⼊⼝:
⽜客⽹:https://www.nowcoder.com/exam/oj
LeetCode:https://leetcode.cn/problems/copy-list-with-random-pointer/description/

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

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

相关文章

一键转换语言,探索四大在线翻译工具的魅力!

各种翻译工具不仅为个人用户提供了极大的便利&#xff0c;也为跨国企业、学术研究和文化交流提供了强有力的支持&#xff0c;接下来为大家推荐几款好用的翻译在线工具&#xff01; 福昕在线翻译 直达链接&#xff1a; https://fanyi.pdf365.cn/ 福昕在线翻译是一款功能强大…

分布式锁 redis与zookeeper

redis实现分布式锁 原理 基于redis命令setnx key value来实现分布式锁的功能&#xff0c;只有当key不存在时&#xff0c;setnx才可以设置成功并返回1&#xff0c;否则设置失败返回0。 方案1&#xff1a; 方案1存在的问题 假如在加锁成功&#xff0c;释放锁之前&#xff0c;…

面向对象08:什么是多态

本节内容视频链接&#xff1a;面向对象12&#xff1a;什么是多态_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV12J41137hu?p71&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 Java中的多态是面向对象编程的一个重要概念&#xff0c;‌它允许不同类型的对象对…

jenkins安装及介绍

Cl:持续集成 CD:持续部署 插件:丰富的插件&#xff0c;可以满足99%的需求&#xff0c;还可以二次开发插件来满足需求 Jenkins能干嘛 1.集成第三方工具的使用&#xff0c;jenkins是一个集大成者&#xff0c;它集成了1000多个插件&#xff0c;几乎把所有知名的工具都集成到ienkin…

职场达人必备:2024年PDF转PPT工具精选指南

PDF文件有卓越的兼容性和安全性&#xff0c;&#xff1b;而PPT则以其强大的演示能力。然而&#xff0c;在日常的工作与学习场景中&#xff0c;我们时常面临将PDF内容转化为PPT格式的需求&#xff0c;以便更好地进行展示与编辑。那么&#xff0c;究竟该如何高效地将PDF转换成PPT…

多维系统下单点登录之整理解决方案

从淘宝天猫的单点登录说起 1.1 SSO单点登录 概述 随着互联网大数据不断发展&#xff0c;应用服务的不断增多&#xff0c;单点登录越来越能够凸显其作用。单点 登录SSO(Single Sign On)&#xff0c;顾名思义就是单个节点登录&#xff0c;全局使用。是目前最为流行的统一登录 解…

36 使用LDT(2)

首先是 定义 两个任务的LDT表 这是再GDT表中的选择子 首先是宏定义&#xff1a;这里的 0x4 , 3 先不用管 这里 一个task 一个LDT表 然后是在GDT表中 增加关于LDT的描述。 这里需要加上一个图。 还是这个图 然后是在 TSS表中&#xff0c;设置LDT的表的地址。 然后是更改 TSS表中…

AI的未来已来:GPT-4商业应用带来的无限可能

随着人工智能技术的快速发展&#xff0c;OpenAI于2023年3月15日发布了多模态预训练大模型GPT-4&#xff0c;这一里程碑式的进步不仅提升了AI的语言处理能力&#xff0c;还拓展了其应用范围。本文将深入探讨GPT-4的技术进步、商业化进程、用户体验改善、伦理和社会影响&#xff…

UR机械臂的ROS驱动安装官方教程详解——机器人抓取系统基础系列(一)

UR机械臂的ROS驱动安装配置官方教程详解——机器人抓取系统基础系列&#xff08;一&#xff09; 前言1 准备工作2 电脑安装驱动3 机器人端设置4 电脑和机器人的通讯IP设置5 启动机械臂的ROS驱动6 MoveIt控制机械臂总结 前言 本文在官方Github教程的基础上&#xff0c;详细阐述…

详细说明:向量数据库Faiss的搭建与使用

当然&#xff0c;Faiss&#xff08;Facebook AI Similarity Search&#xff09;是一个用来高效地进行相似性搜索和密集向量聚类的库。它能够处理大型数据集&#xff0c;并且在GPU上的性能表现尤为出色。下面详细介绍Faiss的搭建与使用。 1. 搭建Faiss 1.1 安装依赖包 首先&a…

Hadoop集群运维管理

Hadoop集群运维管理 一、Hadoop 集群进程管理1.1 NameNode 守护进程管理1.2 DataNode 守护进程管理1.3 ResourceManager 守护进程管理1.4 NodeManager 守护进程管理 二、Hadoop 集群运维技巧2.1 查看日志2.2 清理临时文件2.3 定期执行负载均衡2.4 文件系统检查2.5 元数据备份 三…

Redis的持久化介绍及其Linux配置介绍

1. Redis的持久化 Redis的数据都是存储在内存中,为了数据的永久保存,需要把数据同步到硬盘上,这个过程就叫做持久化. Redis的持久化存在有两种方式: rdb方式,aof方式,这两种方式可以单独使用,也可以综合使用. rdb持久化方式: 是在指定的时间间隔写入硬盘aof持久化方式:是以日…

【Python使用】嘿马python基础入门全体系教程第5篇:容器:字符串、列表、元组、字典,<1>添加元素(“增“append

本教程的知识点为&#xff1a;计算机组成 计算机是由什么组成的&#xff1f; 1. 硬件系统&#xff1a; 2. 软件系统&#xff1a; 目标 运算符的分类 1. 算数运算符 2. 赋值运算符 3. 复合赋值运算符 判断语句和循环语句 if嵌套 1. if嵌套的格式 2. if嵌套的应用 if嵌套执行流程…

链家web安全面试经验分享

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s…

MyBatis使用:动态SQL

1、目标 本文的主要目标是使用MyBatis的动态SQL 2、最好使用Param注解 Data public class BaseEntity {protected String id;protected Integer createUserId;protected String createDateTime;}Data public class News extends BaseEntity {private String title;}RestCont…

【C++ Primer Plus习题】5.8

问题: 解答: #include <iostream> #include <cstring> using namespace std;#define SIZE 20int main() {char words[20];char done[] "done";int count 0;while (true){cout << "请输入单词:" << endl;cin >> words;if …

Open3D 最近点约束的体素滤波(35)

Open3D 最近点约束的体素滤波(35) 一、算法介绍二、算法步骤三、具体代码四、实现效果一、算法介绍 最近点约束的体素滤波,是指在每个体素中,选择距离体素中心最近的原始点作为滤波结果,这样保留的是原始点位置。相比于体素滤波的重心点重新计算,或者八叉树体素中心,更加…

进阶岛 茴香豆:企业级知识库问答工具

一、任务介绍 在 InternStudio 中利用 Internlm2-7b 搭建标准版茴香豆知识助手&#xff0c;并使用 Gradio 界面完成 2 轮问答&#xff08;问题不可与教程重复&#xff0c;作业截图需包括 gradio 界面问题和茴香豆回答&#xff09;。知识库可根据根据自己工作、学习或感兴趣的内…

【复旦微FM33 MCU 外设开发指南】外设篇1——GPIO

前言 本系列基于复旦微FM33系列单片机的DataSheet编写&#xff0c;旨在提供一些开发指南。 本文章及本系列其他文章将持续更新&#xff0c;本系列其它文章请跳转【复旦微FM33 MCU 外设开发指南】总集篇 本文章最后更新日期&#xff1a;2024/08/25 文章目录 前言GPIO工作时钟…

PowerShell 一键配置IP

前言 实现一键更改Windows 网卡IP,子网,网关,dns,重命名网卡,获取的接口索引名称,获取接口名称,刷新组策略,刷新系统,脚本可重复配置,,以下环境我是两个网卡配置IP 前提条件 开启wmi,配置网卡,参考 创建更改网卡脚本 实验环境,两个网卡,清除默认,重命名(配置)…