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

分治算法-leetcode148题

分治算法遵循三个步骤:

  1. ​分解(Divide)​​:将原问题划分为多个子问题,子问题是原问题的较小实例。
  2. ​解决(Conquer)​​:递归解决子问题。若子问题足够小,则直接求解。
  3. ​合并(Combine)​​:将子问题的解合并为原问题的解。

常见的分治算法:

1.归并排序(Merge Sort)​

  • ​原理​​:将数组递归分成两半,分别排序后合并有序子数组。
  • ​特点​​:稳定排序,时间复杂度稳定为 O(nlogn),需额外空间。
  • ​应用场景​​:大数据排序、外部排序(如海量数据文件排序)。

​2. 快速排序(Quick Sort)​

  • ​原理​​:选择基准元素(Pivot),将数组分为“小于基准”和“大于基准”两部分,递归排序。
  • ​特点​​:原地排序,平均时间复杂度 O(nlogn),最坏情况 O(n2)(可通过随机化避免)。
  • ​应用场景​​:内存有限的内部排序,如编程语言标准库中的排序实现。

​3. 二分查找(Binary Search)​

  • ​原理​​:在有序数组中,通过不断缩小搜索范围(折半)快速定位目标值。
  • ​特点​​:时间复杂度 O(logn),无合并步骤,属于分治的简化形式。
  • ​应用场景​​:有序数据的高效查找,如字典、数据库索引。

​4. Strassen 矩阵乘法​

  • ​原理​​:将大矩阵分解为子矩阵,通过7次子矩阵乘法(而非传统8次)降低计算复杂度。
  • ​特点​​:时间复杂度 O(nlog2​7)≈O(n2.81),优于传统 O(n3)。
  • ​应用场景​​:大规模矩阵运算优化,如科学计算、图形学。

​5. 最近点对问题(Closest Pair of Points)​

  • ​原理​​:将点集分为左右两半,分别求最近点对,再检查跨分界线的点对。
  • ​特点​​:时间复杂度 O(nlogn),巧妙利用分治减少计算量。
  • ​应用场景​​:计算几何、碰撞检测、地理信息系统(GIS)。

​6. 大整数乘法(Karatsuba 算法)​

  • ​原理​​:将大整数分解为高位和低位,通过3次乘法替代传统4次,降低计算次数。
  • ​特点​​:时间复杂度 O(nlog2​3)≈O(n1.585),适用于超大数运算。
  • ​应用场景​​:密码学(如RSA加密)、高精度计算库。

​7. 快速傅里叶变换(FFT)​

  • ​原理​​:将多项式分解为偶次项和奇次项,递归转换到频域再合并结果。
  • ​特点​​:将 DFT 计算复杂度从 O(n2) 降至 O(nlogn)。
  • ​应用场景​​:信号处理、图像压缩(如JPEG)、卷积神经网络。

​8. 棋盘覆盖问题​

  • ​原理​​:用L型骨牌覆盖残缺棋盘,递归分割棋盘为四块,处理含残缺的子块。
  • ​特点​​:通过分治将复杂覆盖问题分解为可重复子问题。
  • ​应用场景​​:算法教学案例、拼图游戏逻辑。

​9. 线性时间选择算法(QuickSelect)​

  • ​原理​​:类似快速排序,通过划分操作递归查找第k小元素。
  • ​特点​​:平均时间复杂度 O(n),无需完全排序。
  • ​应用场景​​:统计学中位数计算、Top-K问题(如排行榜)

分治、动态规划、贪心对比

​策略​​适用场景​​关键特点​
​分治​子问题独立且合并简单(如排序)递归分解 + 合并结果
​动态规划​子问题重叠且有最优子结构(如背包)记忆化存储避免重复计算
​贪心​局部最优解能导向全局最优(如Huffman编码)每一步选择当前最优,无回溯

 整体步骤如下:

  1. 递归的终止条件:如果链表为空或者只有一个节点,直接返回,因为已经有序。
  2. 找到链表的中间节点,将链表分成左右两部分。
  3. 递归地对左右两部分进行排序。
  4. 合并排序后的左右两部分。

利用快慢指针找到中间节点,而且有一个很关键的就是一定要把链表从中间节点断开,不然会陷入死循环

代码如下:

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 sortList(ListNode head) {// 终止条件:链表为空或只有一个节点时直接返回if (head == null || head.next == null) {return head;}// 使用快慢指针找到链表的中间节点(分治的关键步骤)ListNode slow = head, fast = head;while (fast.next != null && fast.next.next != null) {slow = slow.next;      // 慢指针每次走一步fast = fast.next.next; // 快指针每次走两步}ListNode mid = slow.next; // 中间节点的下一个节点为右半部分头节点slow.next = null;          // 将链表断开为左右两部分// 递归对左右子链表排序(分治的递归分解)ListNode left = sortList(head); // 左半部分排序ListNode right = sortList(mid); // 右半部分排序// 合并两个已排序的链表(分治的结果合并)return merge(left, right);}// 合并两个有序链表private ListNode merge(ListNode l1, ListNode l2) {ListNode dummy = new ListNode(0); // 创建哑节点作为合并后的链表头ListNode cur = dummy;// 遍历两个链表,按升序连接节点while (l1 != null && l2 != null) {if (l1.val <= l2.val) {cur.next = l1;l1 = l1.next;} else {cur.next = l2;l2 = l2.next;}cur = cur.next;}// 将剩余链表直接连接到末尾cur.next = (l1 != null) ? l1 : l2;return dummy.next;}
}

http://www.xdnf.cn/news/364681.html

相关文章:

  • archlinux 详解系统层面
  • RISC-V AIA SPEC学习(五)
  • Springboot+Vue+Mybatis-plus-Maven-Mysql项目部署
  • 可编辑56页PPT | 化工行业智慧工厂解决方案
  • nvidia-smi 和 nvcc -V 作用分别是什么?
  • 金贝灯光儿童摄影3大布光方案,解锁专业级童趣写真
  • 智能制造单元系统集成应用平台
  • SAM详解3.1(关于2和3的习题)
  • 学习黑客认识Security Operations Center
  • 雷赛伺服L7-EC
  • 抖音 “碰一碰” 发视频:短视频社交的新玩法
  • Midjourney-V7:支持参考图片头像或背景生成新保真图
  • Spring事务传播行为-实践向
  • 软件确认报告:审查功能、评估标准及推动软件稳定高效运行
  • 【Cesium入门教程】第五课:数据源
  • JAVA学习-练习试用Java实现“一个游戏AI :如井字游戏(Tic-Tac-Toe)的AI对手”
  • 【二】CURL命令解析
  • 报错 <pcl/features/feature_evaluation/feature_evaluation_framework.h> 不存在的解决办法
  • Java中的控制流语句:if、switch、for、foreach、while、do-while
  • Redis 8.0携新功能,重新开源
  • 【Unity】Unity中修改网格的大小和倾斜网格
  • 如何解决Jmeter中的乱码问题?
  • 【PHP】基于币安链,一个完整的USDT转账示例
  • 【python】 python拆包
  • 【QT】项目打包与发布安装
  • 图灵爬虫练习平台第七题千山鸟飞绝js逆向
  • 宠物医院预约|基于Java+vue的宠物医院预约平台系统(源码+数据库+文档)
  • windows celery OSError: [WinError 6] 句柄无效
  • ELF-如何学习
  • C++(1):整数常量