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

【优选算法】(第二十七篇)

目录

重排链表(medium)

题目解析

讲解算法原理

编写代码

合并K个升序链表(hard)

题目解析

讲解算法原理

编写代码


重排链表(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给定⼀个单链表 L 的头节点 head ,单链表 L 表⽰为:L(0)→L(1)→…→L(n-1)→L(n)
请将其重新排列后变为:
L(0)→L(n)→L(1)→L(n-1)→L(2)→L(n-2)→…
不能只是单纯的改变节点内部的值,⽽是需要实际的进⾏节点交换。
⽰例1:

输⼊:head=[1,2,3,4]
输出:[1,4,2,3]
⽰例2:


输⼊:head=[1,2,3,4,5]
输出:[1,5,2,4,3]

提⽰:
• 链表的⻓度范围为 [1, 5 * 10(4)]
• 1 <= node.val <= 1000

讲解算法原理

解法:
算法思路:

画图画图画图,重要的事情说三遍~
1. 找中间节点;
2. 中间部分往后的逆序;
3. 合并两个链表

编写代码

c++算法代码:

/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution
{
public:void reorderList(ListNode* head) {// 处理边界情况if(head == nullptr || head->next == nullptr || head->next->next == 
nullptr) return;// 1. 找到链表的中间节点 - 快慢双指针(⼀定要画图考虑 slow 的落点在哪⾥) ListNode* slow = head, *fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}// 2. 把 slow 后⾯的部分给逆序 - 头插法ListNode* head2 = new ListNode(0);ListNode* cur = slow->next;slow->next = nullptr; // 注意把两个链表给断开while(cur){ListNode* next = cur->next;cur->next = head2->next;head2->next = cur;cur = next;}// 3. 合并两个链表 - 双指针ListNode* ret = new ListNode(0);ListNode* prev = ret;ListNode* cur1 = head, *cur2 = head2->next;while(cur1){// 先放第⼀个链表prev->next = cur1;cur1 = cur1->next;prev = prev->next;// 再放第⼆个链表if(cur2){prev->next = cur2;prev = prev->next;cur2 = cur2->next;}}delete head2;delete ret;}
};

java算法代码:

/*** 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) {// 处理边界情况if(head == null || head.next == null || head.next.next == null) return;// 1. 找链表的中间节点 - 快慢双指针(⼀定要画图分析 slow 的落点)ListNode slow = head, fast = head;while(fast != null && fast.next != null){slow = slow.next;fast = fast.next.next;}// 2. 把 slow 后⾯的部分给逆序 - 头插法ListNode head2 = new ListNode(0);ListNode cur = slow.next;slow.next = null; // 把两个链表分离while(cur != null){ListNode next = cur.next;cur.next = head2.next;head2.next = cur;cur = next;}// 3. 合并两个链表 - 双指针ListNode cur1 = head, cur2 = head2.next;ListNode ret = new ListNode(0);ListNode prev = ret;while(cur1 != null){// 先放第⼀个链表prev.next = cur1;prev = cur1;cur1 = cur1.next;// 在合并第⼆个链表if(cur2 != null){prev.next = cur2;prev = cur2;cur2 = cur2.next;}}}
}

合并K个升序链表(hard)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼀个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到⼀个升序链表中,返回合并后的链表。
⽰例1:

输⼊:lists=[[1,4,5],[1,3,4],[2,6]]

输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:[
1->4->5,
1->3->4,
2->6
]
将它们合并到⼀个有序链表中得到。1->1->2->3->4->4->5->6
⽰例2:输⼊:lists=[]输出:[]
⽰例3:输⼊:lists=[[]]输出:[]

提⽰:k==lists.length0<=k<=10^40<=lists[i].length<=500-10^4<=lists[i][j]<=10^4lists[i]按升序排列
lists[i].length的总和不超过10^4

讲解算法原理
解法⼀(利⽤堆):

算法思路:

合并两个有序链表是⽐较简单且做过的,就是⽤双指针依次⽐较链表 1 、链表 2 未排序的最⼩元素,选择更⼩的那⼀个加⼊有序的答案链表中。
合并 K 个升序链表时,我们依旧可以选择 K 个链表中,头结点值最⼩的那⼀个。那么如何快速的得到头结点最⼩的是哪⼀个呢?⽤堆这个数据结构就好啦~
我们可以把所有的头结点放进⼀个⼩根堆中,这样就能快速的找到每次 K 个链表中,最⼩的元素是哪个。

解法⼆(递归/分治):


算法思路:
逐⼀⽐较时,答案链表越来越⻓,每个跟它合并的⼩链表的元素都需要⽐较很多次才可以成功排序。⽐如,我们有8个链表,每个链表⻓为100。
逐⼀合并时,我们合并链表的⻓度分别为(0,100),(100,100),(200,100),(300,100),(400,100),(500,100),(600,100),(700,100)。所有链表的总⻓度共计3600。
如果尽可能让⻓度相同的链表进⾏两两合并呢?这时合并链表的⻓度分别是(100,100)x4,(200,200)x2,(400,400),共计2400。⽐上⼀种的计算量整整少了1/3。
迭代的做法代码细节会稍多⼀些,这⾥给出递归的实现,代码相对简洁,不易写错。
算法流程:
1. 特判,如果题⽬给出空链表,⽆需合并,直接返回;
2. 返回递归结果。
递归函数设计:
1. 递归出⼝:如果当前要合并的链表编号范围左右值相等,⽆需合并,直接返回当前链表;2. 应⽤⼆分思想,等额划分左右两段需要合并的链表,使这两段合并后的⻓度尽可能相等;3. 对左右两段分别递归,合并[l,r]范围内的链表;
4. 再调⽤mergeTwoLists函数进⾏合并(就是合并两个有序链表)

编写代码
解法一代码:

c++算法代码:

/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution
{struct cmp{bool operator()(const ListNode* l1, const ListNode* l2){return l1->val > l2->val;}};
public:ListNode* mergeKLists(vector<ListNode*>& lists) {// 创建⼀个⼩根堆priority_queue<ListNode*, vector<ListNode*>, cmp> heap;// 让所有的头结点进⼊⼩根堆for(auto l : lists)if(l) heap.push(l);// 合并 k 个有序链表ListNode* ret = new ListNode(0);ListNode* prev = ret;while(!heap.empty()){ListNode* t = heap.top();heap.pop();prev->next = t;prev = t;if(t->next) heap.push(t->next);}prev = ret->next;delete ret;return prev;}
};

java算法代码:

/*** 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 ListNode mergeKLists(ListNode[] lists) {PriorityQueue<ListNode> heap = new PriorityQueue<>((v1, v2) -> v1.val 
- v2.val);// 将所有头结点加⼊到⼩根堆中for(ListNode l : lists)if(l != null)heap.offer(l);// 合并ListNode ret = new ListNode(0);ListNode prev = ret;while(!heap.isEmpty()){ListNode t = heap.poll();prev.next = t;prev = t;if(t.next != null) heap.offer(t.next);}return ret.next;}
}
解法二代码:

c++算法代码:

/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution
{
public:ListNode* mergeKLists(vector<ListNode*>& lists) {return merge(lists, 0, lists.size() - 1);}ListNode* merge(vector<ListNode*>& lists, int left, int right){if(left > right) return nullptr;if(left == right) return lists[left];// 1. 平分数组int mid = left + right >> 1;// [left, mid] [mid + 1, right]// 2. 递归处理左右区间ListNode* l1 = merge(lists, left, mid);ListNode* l2 = merge(lists, mid + 1, right);// 3. 合并两个有序链表return mergeTowList(l1, l2);}ListNode* mergeTowList(ListNode* l1, ListNode* l2){if(l1 == nullptr) return l2;if(l2 == nullptr) return l1;// 合并两个有序链表ListNode head;ListNode* cur1 = l1, *cur2 = l2, *prev = &head;head.next = nullptr;while(cur1 && cur2){if(cur1->val <= cur2->val){prev = prev->next = cur1;cur1 = cur1->next;}else{prev = prev->next = cur2;cur2 = cur2->next;}}if(cur1) prev->next = cur1;if(cur2) prev->next = cur2;return head.next;}
};

java算法代码:

/*** 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 ListNode mergeKLists(ListNode[] lists) {return merge(lists, 0, lists.length - 1);}public ListNode merge(ListNode[] lists, int left, int right){if(left > right) return null;if(left == right) return lists[left];// 1. 平分数组int mid = (left + right) / 2;// [left, mid] [mid + 1, right]// 2. 递归处理左右两部分ListNode l1 = merge(lists, left, mid);ListNode l2 = merge(lists, mid + 1, right);// 3. 合并两个有序链表return mergeTwoList(l1, l2);}public ListNode mergeTwoList(ListNode l1, ListNode l2){if(l1 == null) return l2;if(l2 == null) return l1;// 合并两个有序链表ListNode head = new ListNode(0);ListNode cur1 = l1, cur2 = l2, prev = head;while(cur1 != null && cur2 != null){if(cur1.val <= cur2.val){prev.next = cur1;prev = cur1;cur1 = cur1.next;}else{prev.next = cur2;prev = cur2;cur2 = cur2.next;}}if(cur1 != null) prev.next = cur1;if(cur2 != null) prev.next = cur2;return head.next;}
}

相关文章:

【优选算法】(第二十七篇)

目录 重排链表&#xff08;medium&#xff09; 题目解析 讲解算法原理 编写代码 合并K个升序链表&#xff08;hard&#xff09; 题目解析 讲解算法原理 编写代码 重排链表&#xff08;medium&#xff09; 题目解析 1.题目链接&#xff1a;. - 力扣&#xff08;LeetCod…...

学习Flask框架

Flask简介 Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug &#xff0c;模板引擎则使用 Jinja2 。Flask使用 BSD 授权。 Flask也被称为 “microframework” &#xff0c;因为它使用简单的核心&#xff0c;用 extension 增加其他功能。Flask没…...

Elasticsearch:使用 LLM 实现传统搜索自动化

作者&#xff1a;来自 Elastic Han Xiang Choong 这篇简短的文章是关于将结构化数据上传到 Elastic 索引&#xff0c;然后将纯英语查询转换为查询 DSL 语句&#xff0c;以使用特定过滤器和范围搜索特定条件。完整代码位于此 Github repo 中。 首先&#xff0c;运行以下命令安装…...

人脸表情行为识别系统源码分享

人脸表情行为识别系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…...

ThreadLocal原理解析及面试

基本使用 讲原理之前&#xff0c;我简单写个demo小程序说说怎么使用 public class TestThreadLocal {public static void main(String[] args) throws InterruptedException {ThreadLocal<String> tl new ThreadLocal();/**主线程设置了一个值*/tl.set("SSSSSs&…...

探索未来:mosquitto-python,AI领域的新宠

文章目录 探索未来&#xff1a;mosquitto-python&#xff0c;AI领域的新宠背景&#xff1a;为何选择mosquitto-python&#xff1f;库简介&#xff1a;mosquitto-python是什么&#xff1f;安装指南&#xff1a;如何安装mosquitto-python&#xff1f;函数用法&#xff1a;5个简单…...

C++版iwanna1

第一篇目录 开头程序Game.cpp源文件Player.h头文件Player.cpp源文件trigger.h头文件trigger.cpp源文件Cmp.h头文件Cmp.cpp源文件 开头 大家好&#xff0c;我叫这是我58。 程序 Game.cpp源文件 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <c…...

LSTM变种模型

一、GRU 1.概念 GRU&#xff08;门控循环单元&#xff0c;Gated Recurrent Unit&#xff09;是一种循环神经网络&#xff08;RNN&#xff09;的变体&#xff0c;旨在解决标准 RNN 在处理长期依赖关系时遇到的梯度消失问题。GRU 通过引入门控机制简化了 LSTM&#xff08;长短期…...

Python进阶--函数进阶

目录 1. 函数多返回值 2. 函数多种传参方式 (1). 位置参数 (2). 关键字参数 (3). 缺省参数 (4). 不定长参数 3. 匿名函数 (1). 函数作为参数传递 (2). lambda匿名函数 1. 函数多返回值 def return_num():return 1# 返回1之后就不会再向下继续执行函数体return 2 resu…...

elasticsearch 8.2 设置账号密码

背景:单节点集群数据写入测试-CSDN博客 前述项目支持设置账号密码,但8+版本似乎不能那么做了。 ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch. bootstrap check failure [1] of…...

JavaScript代码如何测试?

测试JavaScript代码是确保其功能、性能和可靠性的关键步骤。以下是一些详细的步骤和方法&#xff0c;用于测试JavaScript代码&#xff1a; 1、编写测试用例 首先&#xff0c;你需要为要测试的JavaScript代码编写测试用例。这些用例应该涵盖代码的各种功能和场景&#xff0c;包…...

案例分享—国外ui设计优秀案例

国外企业更注重用户体验设计&#xff0c;倾向于简洁清晰的设计风格&#xff0c;以提高用户的使用体验和操作效率。他们注重“简约至上”的设计理念&#xff0c;认为简洁的设计可以减少用户的认知负担&#xff0c;提高用户的工作效率。 设计师在界面设计中往往更加注重创意性和个…...

在JavaScript中,改变this指向的call,apply,bind有什么区别,原理分别是什么?

在JavaScript中&#xff0c;call、apply和bind方法都是用来改变函数执行时this指向的。 以下通过一个Demo帮助理解&#xff0c;代码如下&#xff1a; var obj {name: lisi,sayHello: function() {console.log(this.name)} } obj.sayHello()// lisifunction sayHello() {conso…...

Redis 缓存策略详解:提升性能的四种常见模式

在现代分布式系统中&#xff0c;缓存是提升性能和减轻数据库负载的关键组件。Redis 作为一种高性能的内存数据库&#xff0c;被广泛应用于缓存层。本文将深入探讨几种常用的 Redis 缓存策略&#xff0c;包括旁路缓存模式&#xff08;Cache-Aside Pattern&#xff09;、读穿透模…...

怎么建设网站吸引并留住客户

如何建设网站吸引并留住客户 在当今数字化时代&#xff0c;网站是企业与客户沟通的重要桥梁。一个设计精良、功能完备的网站不仅能吸引客户的注意&#xff0c;还能有效留住他们。以下是一些建设网站的关键策略。 **1. 用户体验优先** 网站的整体用户体验&#xff08;UX&#x…...

培训行业为什么要搭建自己的知识付费小程序平台?集师知识付费系统 集师知识付费小程序 集师知识服务系统 集师线上培训系统 集师线上卖课小程序

在当今这个信息爆炸的时代&#xff0c;培训行业正面临前所未有的变革与挑战。传统的线下授课模式虽然经典&#xff0c;但在互联网技术的冲击下&#xff0c;其局限性日益凸显。为了更好地适应市场需求&#xff0c;提升服务效率与用户体验&#xff0c;培训行业亟需搭建自己的知识…...

Linux:Linux进程概念

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 文章目录 目录 文章目录 前言 一 冯诺依曼体系结构 二 操作系统(Operator System&#xff09; 2.1 概念 2.2 设计OS的目的 ​编辑 2.3 OS如何进行管理 ​编辑2.4 总结 三 进程的标示符 3.1 基本概念…...

专题九_递归_算法专题详细总结

目录 递归 1.什么是递归&#xff1f; 2.为什么会用到递归&#xff1f; 3.如何理解递归&#xff1f; 1.递归展开的细节图 2.二叉树中的题目 3.宏观看待递归的过程 1) 不要在意细节的展开图 2) 把递归的函数当作一个黑盒 3) 相信这个黑盒一定能够完成这个任务 4.如何写…...

性能赶超GPT-4!多模态检索最新成果刷爆SOTA!顶会思路确定不学?

关注各大顶会的同学们都知道&#xff0c;今年多模态相关的主题可谓是火爆非常&#xff0c;有许多突破性成果被提出&#xff0c;比如最新的多模态检索增强框架MORE&#xff0c;生成性能猛超GPT-4&#xff01; 再比如多模态检索模型MARVEL&#xff0c;在所有基准上实现SOTA&…...

基于 Qwen2.5-0.5B 微调训练 Ner 命名实体识别任务

一、Qwen2.5 & 数据集 Qwen2.5 是 Qwen 大型语言模型的最新系列&#xff0c;参数范围从 0.5B 到 72B 不等。 对比 Qwen2 最新的 Qwen2.5 进行了以下改进&#xff1a; 知识明显增加&#xff0c;并且大大提高了编码和数学能力。在指令跟随、生成长文本&#xff08;超过 8K…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

python基础语法Ⅰ

python基础语法Ⅰ 常量和表达式变量是什么变量的语法1.定义变量使用变量 变量的类型1.整数2.浮点数(小数)3.字符串4.布尔5.其他 动态类型特征注释注释是什么注释的语法1.行注释2.文档字符串 注释的规范 常量和表达式 我们可以把python当作一个计算器&#xff0c;来进行一些算术…...

AT模式下的全局锁冲突如何解决?

一、全局锁冲突解决方案 1. 业务层重试机制&#xff08;推荐方案&#xff09; Service public class OrderService {GlobalTransactionalRetryable(maxAttempts 3, backoff Backoff(delay 100))public void createOrder(OrderDTO order) {// 库存扣减&#xff08;自动加全…...

【AI News | 20250609】每日AI进展

AI Repos 1、OpenHands-Versa OpenHands-Versa 是一个通用型 AI 智能体&#xff0c;通过结合代码编辑与执行、网络搜索、多模态网络浏览和文件访问等通用工具&#xff0c;在软件工程、网络导航和工作流自动化等多个领域展现出卓越性能。它在 SWE-Bench Multimodal、GAIA 和 Th…...