当前位置: 首页 > news >正文

每日一题-单链表排序

为了对给定的单链表按升序排序,我们可以考虑以下解决方法:

思路

  1. 归并排序(Merge Sort):由于归并排序的时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),并且归并排序不需要额外的空间(空间复杂度为 O ( 1 ) O(1) O(1),但实际上需要递归栈空间),这使得它非常适合用来排序链表。通过归并排序对链表进行排序时,节点的值会被有效地排序,同时还保证了时间和空间的复杂度要求。

  2. 链表操作:我们需要将链表分割为两个子链表,递归地对这两个子链表进行排序,然后合并它们。

步骤

  1. 分割链表:通过快慢指针的方法找到链表的中间节点,将链表分为两部分。
  2. 递归排序:递归地对每一部分链表进行排序。
  3. 合并排序后的链表:将两个已排序的链表合并成一个有序链表。

代码实现

struct ListNode {int val;struct ListNode* next;
};/*** 合并两个已经排序的链表*/
#include <stdio.h>
#include <stdlib.h>struct ListNode {int val;struct ListNode* next;
};/*** 合并两个已经排序的链表*/
struct ListNode* merge(struct ListNode* left, struct ListNode* right) {struct ListNode dummy;struct ListNode* p = &dummy;// 合并两个链表while (left != NULL && right != NULL) {if (left->val < right->val) {p->next = left;left = left->next;} else {p->next = right;right = right->next;}p = p->next;}// 如果还有剩余的元素,直接连接到结果链表if (left != NULL) {p->next = left;} else {p->next = right;}return dummy.next;
}/*** 找到链表的中间节点*/
struct ListNode* findMid(struct ListNode* head) {// 添加空指针检查if (head == NULL || head->next == NULL) {return head;}struct ListNode* slow = head;struct ListNode* fast = head->next;  // Changed initial position// 快慢指针找到中点while (fast != NULL && fast->next != NULL) {slow = slow->next;fast = fast->next->next;}return slow;
}/*** 归并排序链表*/
struct ListNode* sortInList(struct ListNode* head) {// 如果链表为空或只有一个元素,直接返回if (head == NULL || head->next == NULL)return head;// 找到链表的中间节点struct ListNode* mid = findMid(head);struct ListNode* right = mid->next;mid->next = NULL; // 分割链表为两部分struct ListNode* left = head;// 递归排序两个子链表left = sortInList(left);right = sortInList(right);// 合并两个排序后的链表return merge(left, right);
}int main() {  // Changed from void main() to int main()// 创建链表: 1 -> 2 -> 3 -> 4 -> 5struct ListNode* pHead1 = (struct ListNode*)malloc(sizeof(struct ListNode));pHead1->val = 1;pHead1->next = (struct ListNode*)malloc(sizeof(struct ListNode));pHead1->next->val = 2;pHead1->next->next = (struct ListNode*)malloc(sizeof(struct ListNode));pHead1->next->next->val = 3;pHead1->next->next->next = (struct ListNode*)malloc(sizeof(struct ListNode));pHead1->next->next->next->val = 4;pHead1->next->next->next->next = (struct ListNode*)malloc(sizeof(struct ListNode));pHead1->next->next->next->next->val = 5;pHead1->next->next->next->next->next = NULL;// 排序链表struct ListNode* result = sortInList(pHead1);// 打印排序后的链表struct ListNode* cur = result;while (cur != NULL) {printf("%d -> ", cur->val);cur = cur->next;}printf("NULL\n");// 释放内存while (result != NULL) {struct ListNode* temp = result;result = result->next;free(temp);}return 0;
}

补充:选择 dummy.nextdummy->next

在代码中,dummy.nextdummy->next 之间的区别取决于你使用的指针类型和编程语言的语法。

区别
  1. dummy.next:这种写法通常用于在结构体中定义成员变量的情况,这种写法适用于对象实例而非指针类型。例如:

    struct ListNode {int val;ListNode* next;  // 这是一个指针成员变量
    };ListNode dummy;
    dummy.next = someNode;  // 直接访问dummy对象的next成员
    
  2. dummy->next:这种写法通常用于通过指针访问结构体的成员。在这种情况下,dummy 是指向结构体的指针,你需要使用箭头操作符 -> 来访问结构体的成员变量。例如:

    ListNode* dummy = new ListNode();
    dummy->next = someNode;  // 使用箭头符号来访问指针dummy的next成员
    

选择 dummy.nextdummy->next

  • dummy.next 是用在我们直接创建一个结构体对象时(即没有使用指针),通过对象访问其成员变量。
  • dummy->next 是用在我们使用结构体指针时,通过指针来访问结构体的成员变量。

代码中的具体情况

在你的归并排序代码中,dummy 是一个结构体对象而不是指针,所以我们使用 dummy.next 来访问结构体成员 next。而如果我们把 dummy 定义为一个指针(即 ListNode* dummy = new ListNode();),那么就应该使用 dummy->next 来访问成员变量。

举个例子
使用结构体对象时:
ListNode dummy;
dummy.next = someNode;  // 直接通过对象访问
使用结构体指针时:
ListNode* dummy = new ListNode();
dummy->next = someNode;  // 使用箭头符号访问成员

总结

  • dummy.next:适用于 dummy 是结构体对象的情况。
  • dummy->next:适用于 dummy 是结构体指针的情况。
    还是挺好理解的,如果定义的是一个结构体,用.,如果定义的是一个结构体指针,用的是->。

解释

  1. merge 函数:将两个已排序的链表合并成一个排序好的链表。我们通过逐个比较节点的值来合并。
  2. findMiddle 函数:使用快慢指针来找到链表的中间节点。快指针每次移动两步,慢指针每次移动一步。当快指针到达链表末尾时,慢指针刚好到达中间位置。
  3. sortInList 函数:这是主要的排序函数,利用归并排序的思想。首先通过 findMiddle 找到中间节点,将链表分为两部分,然后递归地对每一部分链表进行排序,最后用 merge 将排序后的两部分合并。

时间复杂度

  • 归并排序的时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是链表的节点数。
  • 每次递归分割链表的时间复杂度为 O ( n ) O(n) O(n),总共递归的层数为 O ( log ⁡ n ) O(\log n) O(logn),因此总的时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn)

空间复杂度

  • 归并排序的空间复杂度为 O ( n ) O(n) O(n),因为递归栈的空间复杂度是 O ( log ⁡ n ) O(\log n) O(logn),但每次合并需要额外的空间来存储结果链表。

相关文章:

每日一题-单链表排序

为了对给定的单链表按升序排序&#xff0c;我们可以考虑以下解决方法&#xff1a; 思路 归并排序&#xff08;Merge Sort&#xff09;&#xff1a;由于归并排序的时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn)&#xff0c;并且归并排序不需要额外的空间&#xff08;空…...

webpack04服务器配置

webpack配置 entryoutput filenamepathpublicPath 。。 打包引入的基本路径&#xff0c;&#xff0c;&#xff0c;比如引入一个bundle.js,。引用之后的路径就是 publicPathfilename -devServer:static : 静态文件的位置。。。hostportopencompress : 静态资源是否用gzip压缩hi…...

JDK下载安装配置

一.JDK安装配置。 1.安装注意路径,其他直接下一步。 2.配置。 下接第4步. 或者 代码复制: JAVA_HOME D:\Program Files\Java\jdk1.8.0_91 %JAVA_HOME%\bin 或者直接配置 D:\Program Files\Java\jdk1.8.0_91\bin 3.验证(CMD)。 java javac java -version javac -version 二.下…...

30_Redis哨兵模式

在Redis主从复制模式中,因为系统不具备自动恢复的功能,所以当主服务器(master)宕机后,需要手动把一台从服务器(slave)切换为主服务器。在这个过程中,不仅需要人为干预,而且还会造成一段时间内服务器处于不可用状态,同时数据安全性也得不到保障,因此主从模式的可用性…...

NLP三大特征抽取器:CNN、RNN与Transformer全面解析

引言 自然语言处理&#xff08;NLP&#xff09;领域的快速发展离不开深度学习技术的推动。随着应用需求的不断增加&#xff0c;如何高效地从文本中抽取特征成为NLP研究中的核心问题。深度学习中三大主要特征抽取器——卷积神经网络&#xff08;Convolutional Neural Network, …...

《使用 YOLOV8 和 KerasCV 进行高效目标检测》

《使用 YOLOV8 和 KerasCV 进行高效目标检测》 作者&#xff1a;Gitesh Chawda创建日期&#xff1a;2023/06/26最后修改时间&#xff1a;2023/06/26描述&#xff1a;使用 KerasCV 训练自定义 YOLOV8 对象检测模型。 &#xff08;i&#xff09; 此示例使用 Keras 2 在 Colab 中…...

从MySQL迁移到PostgreSQL的完整指南

1.引言 在现代数据库管理中&#xff0c;选择合适的数据库系统对业务的成功至关重要。随着企业数据量的增长和对性能要求的提高&#xff0c;许多公司开始考虑从MySQL迁移到PostgreSQL。这一迁移的主要原因包括以下几个方面&#xff1a; 1.1 性能和扩展性 PostgreSQL以其高性能…...

服务器一次性部署One API + ChatGPT-Next-Web

服务器一次性部署One API ChatGPT-Next-Web One API ChatGPT-Next-Web 介绍One APIChatGPT-Next-Web docker-compose 部署One API ChatGPT-Next-WebOpen API docker-compose 配置ChatGPT-Next-Web docker-compose 配置docker-compose 启动容器 后续配置 同步发布在个人笔记服…...

51单片机 和 STM32 的烧录方式和通信协议的区别

51单片机 和 STM32 的烧录方式和通信协议的区别 1. 为什么51单片机需要额外的软件&#xff08;如ISP&#xff09;&#xff1f; &#xff08;1&#xff09;51单片机的烧录方式 ISP&#xff08;In-System Programming&#xff09;&#xff1a; 51单片机通常通过 串口&#xff08…...

(STM32笔记)十二、DMA的基础知识与用法 第二部分

我用的是正点的STM32F103来进行学习&#xff0c;板子和教程是野火的指南者。 之后的这个系列笔记开头未标明的话&#xff0c;用的也是这个板子和教程。 DMA的基础知识与用法 二、DMA传输设置1、数据来源与数据去向外设到存储器存储器到外设存储器到存储器 2、每次传输大小3、传…...

【优选算法篇】:模拟算法的力量--解决复杂问题的新视角

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;优选算法篇–CSDN博客 文章目录 一.模拟算法二.例题1.替换所有的问号2.提莫攻击3.外观数列4…...

探秘 JMeter (Interleave Controller)交错控制器:解锁性能测试的隐藏密码

嘿&#xff0c;小伙伴们&#xff01;今天咱们要把 JMeter 里超厉害的 Interleave Controller&#xff08;交错控制器&#xff09;研究个透&#xff0c;让你从新手直接进阶成高手&#xff0c;轻松拿捏各种性能测试难题&#xff01; 一、Interleave Controller 深度剖析 所属家族…...

脚本化挂在物理盘、nfs、yum、pg数据库、nginx(已上传脚本)

文章目录 前言一、什么是脚本化安装二、使用步骤1.物理磁盘脚本挂载&#xff08;离线&#xff09;2.yum脚本化安装&#xff08;离线&#xff09;3.nfs脚本化安装&#xff08;离线&#xff09;4.pg数据库脚本化安装&#xff08;离线&#xff09;5.nginx脚本化安装&#xff08;离…...

ESP嵌入式开发环境安装

前期准备&#xff0c;虚拟机&#xff0c;ios镜像&#xff0c;VSCode。 centOS8&#xff1a;centos安装包下载_开源镜像站-阿里云 虚拟机&#xff1a;vmware VSCode&#xff1a;Visual Studio Code - Code Editing. Redefined 如何安装镜像自行查找 完成以上环境后进行一下操…...

Elasticsearch入门学习

Elasticsearch是什么 Elasticsearch 是一个基于 Apache Lucene 构建的分布式搜索和分析引擎、可扩展的数据存储和矢量数据库。 它针对生产规模工作负载的速度和相关性进行了优化。 使用 Elasticsearch 近乎实时地搜索、索引、存储和分析各种形状和大小的数据。 特点 分布式&a…...

黑马linux笔记(03)在Linux上部署各类软件 MySQL5.7/8.0 Tomcat(JDK) Nginx RabbitMQ

文章目录 实战章节&#xff1a;在Linux上部署各类软件tar -zxvf各个选项的含义 为什么学习各类软件在Linux上的部署 一 MySQL数据库管理系统安装部署【简单】MySQL5.7版本在CentOS系统安装MySQL8.0版本在CentOS系统安装MySQL5.7版本在Ubuntu&#xff08;WSL环境&#xff09;系统…...

《软硬协同优化,解锁鸿蒙系统AI应用性能新高度》

在当今数字化时代&#xff0c;鸿蒙系统与人工智能的融合正逐渐成为科技领域的热门话题。如何通过软件和硬件协同优化&#xff0c;进一步提升鸿蒙系统中AI应用的整体性能&#xff0c;成为了开发者和技术爱好者们关注的焦点。 鸿蒙系统与AI应用的融合现状 鸿蒙系统以其独特的微…...

利用 Tree Shaking 提升 React.js 性能

Tree Shaking 是现代 JavaScript 应用中不可或缺的优化技术&#xff0c;它通过移除未使用的代码来减少最终打包的大小。对于 React.js 应用&#xff0c;这一技术尤为重要&#xff0c;因为随着组件和第三方库的增多&#xff0c;打包体积可能迅速膨胀。Tree Shaking 能显著提升加…...

RPC实现原理,怎么跟调用本地一样

回答1 要让⽹络通信细节对使⽤者透明&#xff0c;我们需要对通信细节进⾏封装&#xff0c;我们先看下⼀个 RPC 调⽤的流程涉及到哪些通 信细节&#xff1a; 1. 服务消费⽅&#xff08; client &#xff09;调⽤以本地调⽤⽅式调⽤服务&#xff1b; 2. client stub 接收到调…...

Vue进阶之AI智能助手项目(二)——ChatGPT的调用和开发

AI智能助手项目 service服务端文件目录src目录详解src/index.tschatGPT:src/chatgpt/index.ts前端接口部分src/api/index.tssrc/utils/request/index.tspost方法httpHttpOptionsrc/utils/request/axios.tsLayout布局页面-viewsexception异常页面src/views/exception/404/index…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...