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

【算法训练-链表 七】【排序】:链表排序、链表的奇偶重排、重排链表

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【链表的排序】,使用【链表】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为:目标公司+最近一年+出现频率排序,由高到低的去牛客TOP101去找,只有两个地方都出现过才做这道题(CodeTop本身汇聚了LeetCode的来源),确保刷的题都是高频要面试考的题。

在这里插入图片描述
以及重排链表
在这里插入图片描述

附上题目链接,后期可以依据解题思路反复快速练习,题目按照题干的基本数据结构分类,且每个分类的第一篇必定是对基础数据结构的介绍

链表排序【MID】

单链表的升序排列

题干

直接粘题干和用例

解题思路

而链表中我们也可以用【合并K个有序链表】同样的方式,当链表被划分到只剩一个节点时,就一定有序。只需要找到中间个元素的前一个节点,将其断开,就可以将链表分成两个子链表,然后继续划分,直到最小,然后往上依次合并。

  • 终止条件: 当子链表划分到为空或者只剩一个节点时,不再继续划分,往上合并。
  • 返回值: 每次返回两个排好序且合并好的子链表。
  • 本级任务: 找到这个链表的中间节点,从前面断开,分为左右两个子链表,进入子问题排序。

怎么找中间元素呢?我们可以使用快慢双指针,快指针每次两步,慢指针每次一步,那么快指针到达链表尾的时候,慢指针正好走了快指针距离的一半,为中间元素。

具体做法:

  1. step 1【入参判断】:首先判断链表为空或者只有一个元素,直接就是有序的。
  2. step 2【找中间节点】:准备三个指针,快指针right每次走两步,慢指针mid每次走一步,前序指针left每次跟在mid前一个位置。三个指针遍历链表,当快指针到达链表尾部的时候,慢指针mid刚好走了链表的一半,正好是中间位置。
  3. step 3【划分子问题】:从left位置将链表断开,刚好分成两个子问题开始递归。
  4. step 4【合并子问题】:将子问题得到的链表合并,参考合并两个有序链表。

代码实现

给出代码实现基本档案

基本数据结构链表
辅助数据结构
算法分治
技巧双指针(快慢指针)

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

import java.util.*;/** public class ListNode {*   int val;*   ListNode next = null;*   public ListNode(int val) {*     this.val = val;*   }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param head ListNode类 the head node* @return ListNode类*/public ListNode sortInList (ListNode head) {// 1 入参判断,如果链表只剩一个节点或者空,则直接有序,到达终止条件if (head == null || head.next == null) {return head;}// 2 中间位置为慢指针的下一个节点,奇数节点链表为正中间,偶数则为另一半的开头,所以后半段一定是mid.nextListNode mid= findMidNode(head);// 3 设置后半段链表,断开前后半段链表ListNode newHead = mid.next;mid.next = null;// 4 合并两段有序链表return mergeSortList(sortInList(head), sortInList(newHead));}// 寻找链表中间节点private ListNode findMidNode(ListNode head) {ListNode fast = head;ListNode slow = head;while (fast.next != null && fast.next.next != null) {fast = fast.next.next;slow = slow.next;}// 3 中间位置为慢指针的下一个节点,奇数节点链表为正中间,偶数则为另一半的开头return slow;}// 合并两个有序链表private ListNode mergeSortList(ListNode pHead1, ListNode pHead2) {// 1 入参判断if (pHead1 == null && pHead2 == null) {return null;}if (pHead1 == null) {return pHead2;}if (pHead2 == null) {return pHead1;}// 2 设置结果链表ListNode dummy = new ListNode(-1);ListNode p = dummy;while (pHead1 != null && pHead2 != null) {if (pHead1.val <= pHead2.val) {p.next = pHead1;pHead1 = pHead1.next;} else {p.next = pHead2;pHead2 = pHead2.next;}p = p.next;}// 3 如果其中一个链表为空,后续直接接另一个if (pHead1 == null) {p.next = pHead2;}if (pHead2 == null) {p.next = pHead1;}return dummy.next;}
}

复杂度分析

在这里插入图片描述

链表的奇偶重排【MID】

需要注意的是节点的位置而非节点的值

题干

直接粘题干和用例

解题思路

核心思路就是奇数位节点和偶数位节点断掉重连

  1. step 1:判断空链表的情况,如果链表为空,不用重排。如果链表只有一个节点也不用重排
  2. step 2:使用双指针odd和even分别遍历奇数节点和偶数节点,并给偶数节点链表一个头。
  3. step 3:上述过程,每次遍历两个节点,且even在后面,因此每轮循环用even检查后两个元素是否为NULL,如果不为再进入循环行上述连接过程。
  4. step 4:将偶数节点头接在奇数最后一个节点后,再返回头部。

代码实现

给出代码实现基本档案

基本数据结构链表
辅助数据结构
算法迭代
技巧双指针(同向指针)

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

import java.util.*;/** public class ListNode {*   int val;*   ListNode next = null;*   public ListNode(int val) {*     this.val = val;*   }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param head ListNode类* @return ListNode类*/public ListNode oddEvenList (ListNode head) {// 1 入参条件判断if (head == null) {return null;}if (head.next == null) {// 只有1个节点,不用重排return head;}// 2 设置偶数虚拟头节点,并设定奇偶双指针ListNode odd = head;ListNode evenDummy = head.next;ListNode even = evenDummy;// 3 遍历链表,往奇数和偶数节点上补充对应节点,因为even在后边,所以要以even做判断,否则对于1-2-3-4这种情况//odd结束时指向null,null.next会有问题,返回仍然是nullwhile (even != null && even.next != null) {// 奇数位断开指向偶数的指针并指向下一个奇数位odd.next = even.next;odd = odd.next;// 偶数位断开指向奇数的指针并指向下一个偶数位even.next = odd.next;even = even.next;}// 4 遍历完后偶数整体接到奇数后odd.next = evenDummy;return head;}
}

复杂度分析

时间复杂度:O(n),遍历一次链表的所有节点
空间复杂度:O(1),常数级指针,无额外辅助空间

重排链表【MID】

复杂度升级了一些,不过套路类似

题干

直接粘题干和用例

解题思路

注意到目标链表即为将原链表的左半端和反转后的右半端合并后的结果。这样我们的任务即可划分为三步:

  1. 找到中点】找到原链表的中点(参考「876. 链表的中间结点」)。我们可以使用快慢指针来 O(N)O(N)O(N) 地找到链表的中间节点。
  2. 反转右半边】将原链表的右半端反转(参考「206. 反转链表」)。我们可以使用迭代法实现链表的反转。
  3. 合并两个链表】将原链表的两端合并。因为两链表长度相差不超过 11,因此直接合并即可。

以上需要注意的是,找链表中点时,对于奇数个节点,中点为前半段链表所有(从题目示例可以看出)

代码实现

给出代码实现基本档案

基本数据结构链表
辅助数据结构
算法迭代
技巧双指针

其中数据结构、算法和技巧分别来自:

  • 10 个数据结构:数组、链表、栈、队列、散列表、二叉树、堆、跳表、图、Trie 树
  • 10 个算法:递归、排序、二分查找、搜索、哈希算法、贪心算法、分治算法、回溯算法、动态规划、字符串匹配算法
  • 技巧:双指针、滑动窗口、中心扩散

当然包括但不限于以上

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public void reorderList(ListNode head) {// 1 入参校验if (head == null || head.next == null) {return ;}// 2 找到链表中点,断开后半段链表,这次要找的mid要偏右一些,前半段保留偏长,这样后续交替衔接才没问题ListNode mid = middleNode(head);ListNode l1 = head;ListNode l2 = mid.next;mid.next = null;// 3 反转后半段链表l2 = reverse(l2);// 4 将反转后链表连接到原链表中mergeList(l1, l2);}// 交替合并两个链表private void mergeList(ListNode l1, ListNode l2) {ListNode pNext1;ListNode pNext2;// 因为两个链表仅仅相差1,所以直接交替合并即可while (l1 != null && l2 != null) {// 暂存两个链表的下一个节点pNext1 = l1.next;pNext2 = l2.next;// 交替衔接l1和l2l1.next = l2;l1 = pNext1;l2.next = l1;l2 = pNext2;}}// 寻找中间节点private ListNode middleNode(ListNode head) {ListNode slow = head;ListNode fast = head;while (fast.next != null && fast.next.next != null) {slow = slow.next;fast = fast.next.next;}return slow;}// 反转链表private ListNode reverse(ListNode head) {ListNode pre = null;ListNode cur = head;while (cur != null) {ListNode pNext = cur.next;cur.next = pre;pre = cur;cur = pNext;}return pre;}
}

复杂度分析

时间复杂度:遍历了链表,时间复杂度为O(N)
空间复杂度:没有使用额外空间,空间复杂度为O(1)

相关文章:

【算法训练-链表 七】【排序】:链表排序、链表的奇偶重排、重排链表

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【链表的排序】&#xff0c;使用【链表】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&am…...

LGB的两种写法

方法一 import lightgbm as lgb import pandas as pd from sklearn.model_selection import train_test_split, KFold from sklearn.metrics import accuracy_score# 读取训练集和测试集数据 train_data pd.read_csv(train.csv) test_data pd.read_csv(test.csv)# 分割特征和…...

【Unity的HDRP下ShaderGraph实现权重缩放全息投影_(内附源码)】

实现权重缩放全息投影 效果如下 效果如下 顶点位置偏移 链接&#xff1a; 提取码&#xff1a;1234...

透视俄乌网络战之二:Conti勒索软件集团(上)

透视俄乌网络战之一&#xff1a;数据擦除软件 Conti勒索软件集团&#xff08;上&#xff09; 1. Conti简介2. 组织架构3. 核心成员4. 招募途径5. 工作薪酬6. 未来计划参考 1. Conti简介 Conti于2019年首次被发现&#xff0c;现已成为网络世界中最危险的勒索软件之一&#xff0…...

【华为OD机试python】拔河比赛【2023 B卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 公司最近准备进行拔河比赛,需要在全部员工中进行挑选。 选拔的规则如下: 按照身高优先、体重次优先的方式准备比赛阵容; 规定参赛的队伍派出10名选手。 请实现一个选拔队员的小程序。 输…...

05 CNN 猴子类别检测

一、数据集下载 kaggle数据集[10 monkey] 二、数据集准备 2.1 指定路径 from tensorflow import keras import tensorflow as tf import numpy as np import pandas as pd import matplotlib.pyplot as plttrain_dir /newdisk/darren_pty/CNN/ten_monkey/training/ valid_d…...

【C#】关于Array.Copy 和 GC

关于Array.Copy 和 GC //一个简单的 数组copy 什么情况下会触发GC呢[ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]public static void Copy(Array sourceArray,long sourceIndex,Array destinationArray,long destinationIndex,long length);当源和目…...

Vue前端框架08 Vue框架简介、VueAPI风格、模板语法、事件处理、数组变化侦测

目录 一、Vue框架1.1渐进式框架1.2 Vue的版本 二、VueAPI的风格三、Vue开发准备工作四、模板语法文本插值属性绑定条件渲染列表渲染key管理状态 四、事件处理定义事件事件参数事件修饰符 五、数组变化侦测 一、Vue框架 渐进式JavaScript框架&#xff0c;易学易用&#xff0c;性…...

WebStorm使用PlantUML

虽然 WebStorm 没有官方的 PlantUML 插件&#xff0c;但我们可以使用第三方插件 PlantUML Integration 来实现在 WebStorm 中使用 PlantUML。 以下是使用 PlantUML Integration 插件&#xff0c;在 WebStorm 中设计一个 Vue 模块的步骤&#xff1a; 安装 PlantUML Integratio…...

Python做批处理,给安卓设备安装应用和传输图片

场景&#xff1a;几台新安卓平板过来了&#xff0c;需要安4个应用并复制4张图片。手工操作其实也未尝不可&#xff0c;但是能自动化起来&#xff0c;岂不是美哉。 python调用系统命令&#xff0c;我选用了os.system&#xff0c;最简单粗暴&#xff0c;也能有回显&#xff0c;就…...

如何获取springboot中所有的bean

代码 Component public class TestS {Autowiredprivate Map<String, Object> allBean Maps.newConcurrentMap();public void testA(){System.out.println("测试下");}}这段代码是一个使用 Spring Framework 的依赖注入&#xff08;DI&#xff09;功能的示例。…...

大数据技术之Hadoop:HDFS存储原理篇(五)

目录 一、原理介绍 1.1 Block块 1.2 副本机制 二、fsck命令 2.1 设置默认副本数量 2.2 临时设置文件副本大小 2.3 fsck命令检查文件的副本数 2.4 block块大小的配置 三、NameNode元数据 3.1 NameNode作用 3.2 edits文件 3.3 FSImage文件 3.4 元素据合并控制参数 …...

用C语言实现牛顿摆控制台动画

题目 用C语言实现牛顿摆动画&#xff0c;模拟小球的运动&#xff0c;如图所示 拆解 通过控制台API定位输出小球运动的只是2边小球&#xff0c;中间小球不运动&#xff0c;只需要固定位置输出左边小球上升下降时&#xff0c;X、Y轴增量一致。右边小球上升下降时&#xff0c;X、…...

如何自己开发一个前端监控SDK

最近在负责团队前端监控系统搭建的任务。因为我们公司有统一的日志存储平台、日志清洗平台和基于 Grafana 搭建的可视化看板&#xff0c;就剩日志的采集和上报需要自己实现了&#xff0c;所以决定封装一个前端监控 SDK 来完成日志的采集和上报。 架构设计 因为想着以后有机会…...

node.js笔记

首先&#xff1a;浏览器能执行 JS 代码&#xff0c;依靠的是内核中的 V8 引擎&#xff08;C 程序&#xff09; 其次&#xff1a;Node.js 是基于 Chrome V8 引擎进行封装&#xff08;运行环境&#xff09; 区别&#xff1a;都支持 ECMAScript 标准语法&#xff0c;Node.js 有独立…...

mysql 增量备份与恢复使用详解

目录 一、前言 二、数据备份策略 2.1 全备 2.2 增量备份 2.3 差异备份 三、mysql 增量备份概述 3.1 增量备份实现原理 3.1.1 基于日志的增量备份 3.1.2 基于时间戳的增量备份 3.2 增量备份常用实现方式 3.2.1 基于mysqldump增量备份 3.2.2 基于第三方备份工具进行增…...

9月5日上课内容 第一章 NoSQL之Redis配置与优化

本章结构 关系型数据库和非关系型数据库 概念介绍 ●关系型数据库&#xff1a; 关系型数据库是一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上&#xff0c;一般面向于记录。 SQL 语句&#xff08;标准数据查询语言&#xff09;就是…...

QT 第四天

一、设置一个闹钟 .pro QT core gui texttospeechgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend…...

nrf52832 GPIO输入输出设置

LED_GPIO #define LED_START 17 #define LED_0 17 #define LED_1 18 #define LED_2 19 #define LED_3 20 #define LED_STOP 20设置位输出模式&#xff1a; nrf_gpio_cfg_output(LED_0); 输出高电平:nrf_gpio_pin_set(LED_0); 输…...

MyBatis 动态 SQL 实践教程

一、MyBatis动态 sql 是什么 动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中&#xff0c;开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。例如&#xff0c;拼接时要确保添加了必要的空格&#xff0c;还要注意去掉列…...

CSS 斜条纹进度条

效果&#xff1a; 代码&#xff1a; html: <div class"active-line flex"><!-- lineWidth&#xff1a;灰色背景 --><div class"bg-line"><div v-for"n in 30" class"gray"></div></div><div…...

JavaScript(1)每天10个小知识点

​ 目录 1. JavaScript 有哪些数据类型&#xff0c;它们的区别&#xff1f;**2. 数据类型检测的方式有哪些**3. null 和 undefined 区别**4. intanceof 操作符的实现原理及实现**5. 如何获取安全的 undefined 值&#xff1f;**6. Object.is() 与比较操作符 “”、“” 的区别*…...

scanf和scanf_s函数详解

目录 引言&#xff1a; 1.scanf函数的用法&#xff1a; 2.scanf_s函数的用法&#xff1a; 3.scanf和scanf_s的区别&#xff1a; 结论&#xff1a; 引言&#xff1a; 在C语言中&#xff0c;输入函数scanf是非常常用的函数之一&#xff0c;它可以从标准输入流中读取数据并将其…...

基于SSM的在线购物系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

认识JVM的内存模型

从上一节了解到整个JVM大的内存区域&#xff0c;分为线程共享的heap&#xff08;堆&#xff09;&#xff0c;MethodArea&#xff08;方法区&#xff09;&#xff0c;和线程独享的 The pc Register&#xff08;程序计数器&#xff09;、Java Virtual Machine Stacks&#xff08;…...

Java8实战-总结19

Java8实战-总结19 使用流映射对流中每一个元素应用函数流的扁平化 使用流 映射 一个非常常见的数据处理套路就是从某些对象中选择信息。比如在SQL里&#xff0c;你可以从表中选择一列。Stream API也通过map和flatMap方法提供了类似的工具。 对流中每一个元素应用函数 流支持…...

论文浅尝 | 训练语言模型遵循人类反馈的指令

笔记整理&#xff1a;吴亦珂&#xff0c;东南大学硕士&#xff0c;研究方向为大语言模型、知识图谱 链接&#xff1a;https://arxiv.org/abs/2203.02155 1. 动机 大型语言模型&#xff08;large language model, LLM&#xff09;可以根据提示完成各种自然语言处理任务。然而&am…...

【云计算网络安全】解析DDoS攻击:工作原理、识别和防御策略 | 文末送书

文章目录 一、前言二、什么是 DDoS 攻击&#xff1f;三、DDoS 攻击的工作原理四、如何识别 DDoS 攻击五、常见的 DDoS 攻击有哪几类&#xff1f;5.1 应用程序层攻击5.1.1 攻击目标5.1.2 应用程序层攻击示例5.1.3 HTTP 洪水 5.2 协议攻击5.2.1 攻击目标5.2.2 协议攻击示例5.2.3 …...

64位Linux系统上安装64位Oracle10gR2及Oracle11g所需的依赖包

在64位Linux系统上安装64位Oracle 10gR2,到底需要装哪些包? 这不是一个完整的安装教程,仅仅探讨在64位CentOS 5.8系统上安装64位Oracle 10gR2,到底需要装哪些RPM包. 实验环境VMWare Workstation 8.0 Linux发行版: CentOS 5.8 x86_64 Kernel版本: 2.6.18-308.el5 Oracle Dat…...

Unity InputSystem 基础使用之鼠标交互

资料 官方文档 导入InputSystem包 Package Manager 搜索Input System进行下载启用该包&#xff0c;会重启Unity Editor 注意 InputSystem可以和旧版输入系统一起使用 设置&#xff1a;Project Settings->Player->Other Settings->Configuration->Active Input…...

工程施工行业在哪个网站容易找事做/搜索词分析工具

设计函数分别求两个一元多项式的乘积与和。 输入格式: 输入分2行&#xff0c;每行分别先给出多项式非零项的个数&#xff0c;再以指数递降方式输入一个多项式非零项系数和指数&#xff08;绝对值均为不超过1000的整数&#xff09;。数字间以空格分隔。 输出格式: 输出分2行&…...

wordpress系列文章/seo专业培训中心

问题报错&#xff1a; Plugin execution not covered by lifecycle configuration: org.apache.maven.plugins:maven-resources-plugin:2.6:resources 问题原因&#xff1a; m2e在其执行maven的生命周期管理时没有定义该插件 解决办法&#xff1a; 1、eclipse&#xff1a…...

宠物网站建设的可行性/天津优化公司

目录前言构建一颗二叉树声明实现二叉树的遍历求一颗二叉树的结点个数求二叉树叶子结点的个数求二叉树第K层结点的个数查找数的层序遍历广度优先销毁判断完全二叉树oj练习前言 由于二叉树是数据结构中偏难的一块&#xff0c;这里我们先熟悉二叉树的结构&#xff0c;再具体来实现…...

深圳做网站企业/如何制作一个网页网站

没有悬念&#xff0c;一年一度的天猫双11购物节又创下了新的纪录。 2018年天猫双11购物狂欢节21秒破10亿元&#xff0c;比去年快7秒&#xff1b;1小时47分26秒破千亿元&#xff0c;比去年快7个多小时&#xff1b;15小时49分39秒超1682亿元&#xff0c;超过去年全天交易额&…...

北京微网站建设设计服务/推广网站模板

Java中有八大基本数据类型byte类型:byte类型&#xff0c;使用一个字节存放一个数据&#xff0c;一个字节占八位&#xff0c;所以它取值范围是:1000 0000 ~ 0111 1111(-128-127)为什么不是0000 0000 ~ 1111 1111呢&#xff1f;我们都知道1111 1111 是负数的最大值&#xff0c;因…...

普宁做男科检查长江网站L/阜新网络推广

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 在运行项目的时候&#xff0c;eclipse弹出提示框“Could not open Selected VM debug port (8700). Make sure you do not have another instance of DDMS or of the eclipse plugin running. If it…...