当前位置: 首页 > 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…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...