分治算法刷题总结

news/2025/12/14 20:15:27/文章来源:https://www.cnblogs.com/lliujiang/p/19287594

148. 排序链表

两个思路,一种是从顶向下的排序,另外的一种是从低向上的归并排序,归并排序的复杂度是NLogN

class Solution {public ListNode sortList(ListNode head) {if (head == null || head.next == null)return head;ListNode fast = head.next, slow = head;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}ListNode tmp = slow.next;slow.next = null;ListNode left = sortList(head);ListNode right = sortList(tmp);ListNode h = new ListNode(0);ListNode res = h;while (left != null && right != null) {if (left.val < right.val) {h.next = left;left = left.next;} else {h.next = right;right = right.next;}h = h.next;}h.next = left != null ? left : right;return res.next;}
}作者:Krahets
链接:https://leetcode.cn/problems/sort-list/solutions/13728/sort-list-gui-bing-pai-xu-lian-biao-by-jyd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

不傻!这段比刚才那段简单多了,它用的是——

“递归版归并排序”,思路跟“二分法”一模一样。


🧠 一句话先背住:

把链表从中间劈成两半左边排好序右边排好序,再合并两个有序链表


🌰 举个例子:

链表还是:

4 -> 2 -> 1 -> 3

🧩 第一步:找中间节点(快慢指针)

ListNode fast = head.next, slow = head;
while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;
}

👉 slow 最后会停在中间节点的前一个
上图:

4 -> 2 -> 1 -> 3
↑    ↑
head slow
↑         ↑fast

最后 slow 停在 2,fast 停在 null,于是:

slow.next = 1 -> 3

🧩 第二步:从中间“掰断”

ListNode tmp = slow.next;
slow.next = null;

👉 现在链表被分成两半:

  • 左边:4 -> 2
  • 右边:1 -> 3

🧩 第三步:递归排序两边

ListNode left = sortList(head);   // 把左边排好
ListNode right = sortList(tmp);   // 把右边排好

👉 就像老师把全班分成两半,分别找两个班长把各半边排好序。


🧩 第四步:合并两个有序链表(merge)

ListNode h = new ListNode(0);
ListNode res = h;
while (left != null && right != null) {if (left.val < right.val) {h.next = left;left = left.next;} else {h.next = right;right = right.next;}h = h.next;
}
h.next = left != null ? left : right;

👉 就是谁小谁先上,最后把剩下的直接接上。


🧩 第五步:返回排好序的头

return res.next;

✅ 总结一句话(给你背下来):

这段代码就是先把链表从中间劈开,左右分别排好序,再合并,跟“分糖果”一样:一人一半,先各自理好,再合起来。


🎁 文字版动画:

原始:4 -> 2 -> 1 -> 3劈开:左:4 -> 2右:1 -> 3递归左:再劈:4 和 2合并:2 -> 4递归右:再劈:1 和 3合并:1 -> 3最后合并:2 -> 41 -> 3
→ 1 -> 2 -> 3 -> 4 ✅

🧑‍🏫 送你一句人话:

它就像把一堆乱牌从中间撕开,左右两半分别理好,再合起来,一直撕到只剩一张牌为止。


🎯 小口诀(背下来):

找中间,劈两半,
左右排好再合并。

如果你想,我可以给你画成流程图,或者打印每一步的链表长什么样。要不要?

🎯 一句话先回答:

奇数也不怕,慢指针会停在“前半部分的最后一个节点”,后半部分多一个节点而已。


🧠 举个例子给你看:

假设链表是:

1 -> 2 -> 3 -> 4 -> 5

(5 个节点,奇数)


🔍 快慢指针怎么走:

java复制

ListNode fast = head.next; // 快指针先走一步
ListNode slow = head;      // 慢指针从头开始

表格复制

回合 fast 指向 slow 指向 说明
初始 2 1 快指针先走一步
第1步 4 2 各走一步
第2步 null 3 快指针再走两步,停住

✂️ 此时:

  • slow 停在 3
  • tmp = slow.next 就是 4 -> 5
  • slow.next = null 把链表掰断:

复制

前半:1 -> 2 -> 3
后半:4 -> 5

✅ 结论:

表格复制

节点总数 前半部分 后半部分
偶数 一半 一半
奇数 少一个 多一个

🧑‍🏫 送你一句人话:

慢指针就像“剪刀手”, 总是站在前半部分的尾巴上 ,后半部分哪怕多一个节点,也能稳稳接住。


🎯 小口诀(背下来):

复制

奇偶无所谓,慢针剪中间,
前半少一个,后半全接住。

如果你想,我可以给你 画成动画流程图 ,或者 打印每一步指针的位置 。要不要?

class Solution {public ListNode sortList(ListNode head) {if (head == null) {return head;}int length = 0;ListNode node = head;while (node != null) {length++;node = node.next;}ListNode dummyHead = new ListNode(0, head);for (int subLength = 1; subLength < length; subLength <<= 1) {ListNode prev = dummyHead, curr = dummyHead.next;while (curr != null) {ListNode head1 = curr;for (int i = 1; i < subLength && curr.next != null; i++) {curr = curr.next;}ListNode head2 = curr.next;curr.next = null;curr = head2;for (int i = 1; i < subLength && curr != null && curr.next != null; i++) {curr = curr.next;}ListNode next = null;if (curr != null) {next = curr.next;curr.next = null;}ListNode merged = merge(head1, head2);prev.next = merged;while (prev.next != null) {prev = prev.next;}curr = next;}}return dummyHead.next;}public ListNode merge(ListNode head1, ListNode head2) {ListNode dummyHead = new ListNode(0);ListNode temp = dummyHead, temp1 = head1, temp2 = head2;while (temp1 != null && temp2 != null) {if (temp1.val <= temp2.val) {temp.next = temp1;temp1 = temp1.next;} else {temp.next = temp2;temp2 = temp2.next;}temp = temp.next;}if (temp1 != null) {temp.next = temp1;} else if (temp2 != null) {temp.next = temp2;}return dummyHead.next;}
}作者:力扣官方题解
链接:https://leetcode.cn/problems/sort-list/solutions/492301/pai-xu-lian-biao-by-leetcode-solution/ 
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
这短短挨骂好难理解, 请帮助我理解,我是个傻瓜

你一点都不傻,这段代码确实信息密度很高,而且用了一些“技巧”让人第一眼很难看懂。
我来用最通俗的方式给你讲清楚它到底在干嘛,一句一句拆给你看,就像讲故事一样。


🧠 先记住一句话:

这段代码是在用“归并排序”的思想,给链表排序,但没用递归,而是从下到上,一步一步合并


🌰 举个例子:

假设链表是:

4 -> 2 -> 1 -> 3

我们要把它排成:

1 -> 2 -> 3 -> 4

🧩 第一步:先数长度(就是数数)

int length = 0;
ListNode node = head;
while (node != null) {length++;node = node.next;
}

👉 就是从头走到尾,看看有几个节点。
比如 4->2->1->3,长度就是 4。


🧩 第二步:准备“假头”

ListNode dummyHead = new ListNode(0, head);

👉 这是链表的“万能技巧”:
弄个假的头节点,这样不管怎么变,真头都不会丢


🧩 第三步:开始“从小到大”合并

for (int subLength = 1; subLength < length; subLength <<= 1)

👉 这句话是核心!

  • subLength 一开始是 1,每次翻倍(<<=1 就是乘以 2)
  • 意思是:先两两合并,再四四合并,再八八合并……直到整个链表有序

🧩 第四步:每次“切两段”出来合并

ListNode head1 = curr;
for (int i = 1; i < subLength && curr.next != null; i++) {curr = curr.next;
}
ListNode head2 = curr.next;
curr.next = null;

👉 这就是把链表切成两段,每段长度最多是 subLength。比如第一次 subLength = 1,那就是:

  • head1 是 4
  • head2 是 2
    然后把它俩合并成一段有序的小链表

🧩 第五步:合并两段(merge函数)

ListNode merged = merge(head1, head2);

👉 这个 merge 函数就是你熟悉的合并两个有序链表,谁小谁先上。


🧩 第六步:把合并好的接回去

prev.next = merged;
while (prev.next != null) {prev = prev.next;
}

👉 把合并好的那段接回主链表,然后 prev 走到最后,准备下一次合并。


🧩 第七步:继续下一轮

curr = next;

👉 刚才切完两段后,可能后面还有,就继续切继续合并。


✅ 总结一句话(给你背下来):

这段代码就是把链表先切成小段,小段排好序,再慢慢合并成大段,直到整个链表有序。
只不过它没用递归,而是从下到上,一步一步来,所以看起来有点绕。


🎁 我给你画个图(文字版):

初始:4 -> 2 -> 1 -> 3subLength = 1:合并 [4] 和 [2] → 2 -> 4合并 [1] 和 [3] → 1 -> 3
结果:2 -> 4 -> 1 -> 3subLength = 2:合并 [2->4] 和 [1->3] → 1 -> 2 -> 3 -> 4
结果:1 -> 2 -> 3 -> 4 ✅

🧑‍🏫 最后送你一句人话:

它就像打牌时理牌:先一张一张理好,再两张两张理好,再四张四张……直到全部理完。


如果你愿意,我可以给你重写成超级傻瓜版代码,每一步都带注释,甚至打印出来那种。你要吗?

427. 建立四叉树

题目比较难看明白,实际上连接了该能很快的写出来,说白了,就是一个递归的处理,先处理最左上交的元素,然后划分格子去处理,得到四个格子的数据

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

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

相关文章

IPv4地址与IPv6地址

如大家所了解的&#xff0c;互联网协议地址&#xff08;Internet Protocol Address&#xff0c;简称IP地址&#xff09;&#xff0c;是分配给网络上使用互联网协议&#xff08;IP&#xff09;的每个设备&#xff08;如计算机、服务器、智能手机等&#xff09;的数字标签。IP地址…

Fluent中颗粒流模拟的门道

Fluent的颗粒流 稀疏颗粒常使用DPM模型进行解决 不考虑颗粒碰撞变形&#xff0c;但考虑颗粒之间的碰撞行为&#xff0c;可以使用欧拉颗粒流模型 考虑颗粒碰撞摩擦以及变形&#xff0c;可以使用其内置的DEM模型&#xff0c;也可以采用与其他DEM软件耦合处理 考虑颗粒在运动过程…

31、Ubuntu 服务器虚拟化与 KVM 配置指南

Ubuntu 服务器虚拟化与 KVM 配置指南 在当今的系统管理领域,虚拟化技术无疑是最热门的趋势之一。通过虚拟化,你能够在同一硬件上创建多个 Ubuntu 实例,并且为每个虚拟机分配服务器的部分资源。现代服务器拥有强大的处理能力,借助虚拟化技术,你可以充分挖掘硬件的潜力。本…

官宣:汇纳科技收购华速实业;融速科技完成A+轮融资;3D打印单季破40亿美元|库周报

2025年12月14日&#xff0c;以下是过去一周内3D打印行业发生的事情&#xff0c;包括“大事件” 、“行业动态” 、“趣制造” 、“融资/并购” 、“新产品”等内容。—— 大事件 ——正式官宣&#xff01;汇纳科技收购华速实业12月13日&#xff0c;汇纳科技全资子公司金石汇纳宣…

详谈:解释器模式(二)

接上文。看到这个需求&#xff0c;我们很容易想到一种写法&#xff1a;将输入的字符串分割成单个字符&#xff0c;把数字字符通过switch-case转换为数字&#xff0c;再通过计算符判断是加法还是减法&#xff0c;对应做加、减计算&#xff0c;最后返回结果即可。计划的确可行&am…

新能源逆变器那些事儿:阻抗建模、扫频验证与稳定性分析

并网逆变器阻抗建模&#xff0c;扫频模型扫频验证&#xff0c;仿真模型稳定性分析&#xff0c;功率控制 新能源 变流器 逆变器 虚拟同步控制 逆变器 复现 逆变器阻抗建模及阻抗扫描验证序阻抗建模与稳定性分析 可设置扫描范围、扫描点数 程序附带注释 包括 逆变器仿真模型&…

OpenAI 放大招!GPT-5.2 重磅发布:碾压谷歌 Gemini,替你做 PPT / 写代码,国内这样用最划算

OpenAI放大招&#xff01;GPT-5.2重磅发布&#xff1a;碾压谷歌Gemini&#xff0c;替你做PPT/写代码&#xff0c;国内这样用最划算 昨晚&#xff0c;AI圈炸了&#xff01;OpenAI如期推出新模型GPT-5.2&#xff0c;这次直接瞄准“专业知识型工作”——不管是做PPT、写代码&…

AI时代的云安全(一)新挑战与应对思考

引言 云计算与人工智能的深度融合正在重塑数字基础设施的底层逻辑。当企业竞相将大语言模型、生成式AI服务部署至云端&#xff0c;传统云安全模型正面临前所未有的压力。这种压力并非简单的威胁数量增加&#xff0c;而是源于AI技术特性与云原生架构交织后产生的系统性风险位移—…

中国板材品牌哪家好?山东亦木,环保板材/全屋定制板材/装修环保板材/衣柜专用板材/桦木板/FOSB板/橡胶木/多层板/颗粒板定制实力厂家,老牌子,质量稳定性价比高 - 全局中转站

随着绿色环保理念的深入人心和消费者对家居品质要求的不断提升,优质的板材成为打造健康舒适居家环境的重要基础。在2025年的板材市场中,亦木凭借其创新的商业模式、卓越的产品品质和全方位的赋能服务,成为众多全屋定…

技术满分,增长零分?互联网项目的广告投放破局指南

如果你的团队能攻克复杂的技术架构&#xff0c;却为每月如何稳定获取1000个真实用户而焦虑&#xff0c;那么这篇文章正是为你而写。我们知道&#xff0c;互联网工作室的核心困境往往不在产品本身&#xff0c;而在于 “如何让产品被看见、被使用、被付费” 。你面临的可能不是一…

Java赋能AI智能采编:让百万传媒人提早下班的行业变革方案

Java赋能AI智能采编&#xff1a;让百万传媒人提早下班的行业变革方案 在信息爆炸的今天&#xff0c;传媒行业正面临着“素材多到理不清、稿件改到熬大夜、发布急到踩deadline”的普遍困境。数百万传媒从业者坚守在出版、新闻、广播等岗位上&#xff0c;支撑着年产值超2.5万亿元…

CF1039A Timetable - crazy-

构造 题意 有 \(n\) 辆公交车从车站 A 到车站 B,最短行驶时间为 \(t\)。已知:A 站出发时刻表 \(a_1 < a_2 < \dots < a_n\) 每辆公交车到达 B 站后,B 站会有一个到达时刻表 \(b_1 < b_2 < \dots <…

基于泰坦尼克号数据集的随机森林算法实战

数据预处理 ​ 选取 Pclass &#xff08;船舱等级&#xff09;、 Sex &#xff08;性别&#xff09;、 Age &#xff08;年龄&#xff09;作为特征&#xff0c; Survived &#xff08;是否存活&#xff09;作为标签。 ​用均值填充年龄空值&#xff0c;避免缺失值影响模型训练&…

图片转文字技术(一)从光学识别到智能理解的演进之路

引言 在数字化浪潮中&#xff0c;图片转文字技术已悄然渗透到我们日常生活的方方面面。从手机相册中提取证件信息&#xff0c;到扫描纸质文档生成可编辑文本&#xff1b;从自动驾驶汽车识别路牌&#xff0c;到视障人士通过屏幕阅读器获取图像内容——这项技术的应用场景正在不断…

亿赛通脚本远程调试配置技巧

要进行远程调试&#xff0c;主要是对 Tomcat 和 Java进程 进行调试。以下是针对该系统的远程调试配置方法&#xff1a; 一、Tomcat远程调试配置 1. 修改Tomcat启动脚本 找到Tomcat的启动脚本&#xff08;通常在/esafenet/tomcat/bin/catalina.sh或startup.sh&#xff09;&#…

【大模型预训练】17-分布式并行策略:Tensor并行、Pipeline并行的应用场景

引言在深度学习领域&#xff0c;随着模型复杂性和数据规模的不断增长&#xff0c;传统的单节点计算资源已难以满足高效训练的需求。分布式并行策略因此应运而生&#xff0c;成为提升深度学习训练效率和扩展性的关键手段。其中&#xff0c;Tensor并行和Pipeline并行作为两种主流…

蛇形矩阵(三角形版本)

一开始&#xff0c;发现了规律&#xff0c;但是不知道怎么表示&#xff0c;一开始觉得用多个for循环直接计算得出&#xff0c;后面想了一下&#xff0c;肯定会超时&#xff0c;而且复杂程度很高于是问了问了同学之后&#xff0c;才有的用数组的想法&#xff0c;但是要考虑到要多…

Dockerfile 详解

一、Dockerfile 基础概念 1.1 什么是 Dockerfile&#xff1f; Dockerfile 是一个文本文件&#xff0c;包含了一系列用于构建 Docker 镜像的指令。它遵循特定的格式和语法&#xff0c;Docker 引擎通过读取这些指令来自动化构建镜像。以下是其基础示例&#xff1a; FROM ubuntu:2…

探索非线性电液伺服系统:从PID到反步控制的奇妙之旅

非线性电液伺服系统精确模型反步控制。 pdf教程matlab/simulink源码。 与pid控制对比。嘿&#xff0c;各位技术宅们&#xff01;今天咱们要一起钻进非线性电液伺服系统的神秘世界&#xff0c;好好聊聊精确模型反步控制这一厉害的技术&#xff0c;顺便还会把它和经典的PID控制来…

【大模型预训练】18-分布式并行技术:梯度同步、参数服务器架构实现方法

引言分布式并行技术在深度学习领域的重要性不言而喻&#xff0c;尤其是在处理大规模数据和复杂模型时&#xff0c;其作用尤为显著。随着深度学习模型的不断发展和数据量的爆炸式增长&#xff0c;传统的单机训练方式已难以满足高效计算的需求。分布式并行技术通过将计算任务分配…