尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

分治算法

分治算法
📅 发布时间:2026/7/12 19:45:37

分治算法 (Divide and Conquer)

像“分家再合并”一样,把一个大问题拆成几个规模更小、相互独立的同类小问题。小问题各自解决后,再把它们的结果合并起来,最终得到大问题的答案。

经典问题推演:归并排序

分解:将包含 n 个元素的数组从中间劈开,分为左右两个 n/2 的子数组。
求解:递归地对左右两个子数组进行归并排序。当子数组只剩 1 个元素时,触发递归出口,天然有序。
合并:使用双指针,依次比较左右两个有序子数组的头部,将较小的元素放入辅助数组,最终合并成一个完整的有序数组。

最大子数组和问题 (Maximum Subarray Problem)

问题描述:给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:输入 [-2, 1, -3, 4, -1, 2, 1, -5, 4],输出 6(因为连续子数组 [4, -1, 2, 1] 的和最大,为 6)。

为什么用分治法?

如果用暴力法,需要双重循环,时间复杂度是 \(O(n^2)\)O。而用分治法,我们可以将时间复杂度降到 \(O(nlign)\)。

核心思想:跨越中点的“三种情况”
我们将数组从中间一分为二,那么“最大子数组”只可能出现在以下三种情况中:
完全在左半边:不跨越中点。
完全在右半边:不跨越中点。
跨越中点:一部分在左半边,一部分在右半边。

核心代码

#include <stdio.h>// 辅助函数:求两个数中的最大值
int max(int a, int b) { return a > b ? a : b; }// 处理跨越中点的最大子数组和
int maxCrossingSum(int arr[], int left, int mid, int right) {// 1. 从 mid 向左扫描,求包含 arr[mid] 的左半边最大和int leftSum = -999999, sum = 0;for (int i = mid; i >= left; i--) {sum += arr[i];if (sum > leftSum) leftSum = sum;}// 2. 从 mid+1 向右扫描,求包含 arr[mid+1] 的右半边最大和int rightSum = -999999; sum = 0;for (int i = mid + 1; i <= right; i++) {sum += arr[i];if (sum > rightSum) rightSum = sum;}// 3. 左右两部分相加,即为跨越中点的最大和return leftSum + rightSum;
}// 分治法主函数
int maxSubArray(int arr[], int left, int right) {// 1. 递归出口:区间只有一个元素时,最大和就是它自己if (left == right) return arr[left];// 2. 分解(Divide):找到中点int mid = left + (right - left) / 2;// 3. 求解(Conquer):分别求左半边和右半边的最大子数组和int leftMax = maxSubArray(arr, left, mid);int rightMax = maxSubArray(arr, mid + 1, right);// 4. 求解跨越中点的最大子数组和int crossMax = maxCrossingSum(arr, left, mid, right);// 5. 合并(Combine):三者取最大值return max(max(leftMax, rightMax), crossMax);
}int main() {int arr[] = {-2, 1, -3, 4, -1, 2, 1, -5, 4};int n = sizeof(arr) / sizeof(arr[0]);printf("最大子数组和为:%d\n", maxSubArray(arr, 0, n - 1));return 0;
}

示例推演

以数组 [-2, 1, -3, 4, -1] 为例(下标 0 到 4):

第 1 层分解
目标:将问题一分为二。
中点 mid = 2(元素 -3)。
原问题被拆分为:
左子问题:[-2, 1, -3] (下标 0~2)
右子问题:[4, -1] (下标 3~4)
跨越问题:必须包含 -3 和 4

第 2 层分解(处理左子问题 [-2, 1, -3])
中点 mid = 1(元素 1)。
左左:[-2] -> 递归到底,返回 -2。
左右:[1, -3] -> 继续拆分...(最终求得最大为 1)。
跨越:从 1 往左找最大和(1),从 -3 往右找最大和(-3),跨越和为 -2。
左子问题合并结果:max(-2, 1, -2) = 1。
第 2 层分解(处理右子问题 [4, -1])
中点 mid = 3(元素 4)。
右左:[4] -> 返回 4。
右右:[-1] -> 返回 -1。
跨越:4 + (-1) = 3。
右子问题合并结果:max(4, -1, 3) = 4。
第 1 层合并(处理跨越中点的问题)
目标:计算必须包含 -3 和 4 的最大和。
从 -3 向左扫描:-3,然后 -3 + 1 = -2,然后 -2 + (-2) = -4。向左最大和为 -2(只取 1 和 -3 不如只取 1,但这里必须包含 -3,所以向左最多是 1 + (-3) = -2)。注:实际代码中向左扫描包含mid,最大值为 -2。
从 4 向右扫描:4,然后 4 + (-1) = 3。向右最大和为 4。
跨越中点的最大和:-2 + 4 = 2。

最终合并
比较三种情况:左半边最大(1),右半边最大(4),跨越最大(2)。
三者取最大值:4。
(注:如果数组是 [-2, 1, -3, 4, -1, 2, 1],最终跨越中点的和会是 6,成为全局最大值)。

时间复杂度:根据主定理,递推公式为
\(T(n)=2T(n/2)+O(n)\) ,时间复杂度为 \(O(nlogn)\) 。
核心难点:分治法的难点永远在合并(Combine)阶段。对于最大子数组问题,跨越中点的计算不能简单相加,必须分别向左、向右扫描求最大和。

相关新闻

  • vLLM部署Kimi-K2.5-W4A8完整教程:从环境搭建到服务上线
  • Rider 2024.2 + EmmyLua 1.5.0:Unity C#与Lua双模式调试的3种连接策略对比
  • AI+城市配送网络:多级仓储+动态路由+需求预测

最新新闻

  • 植物基导电 / 储能轻量化生物材料(新能源高端蓝海)
  • Midjourney材质渲染失效案例深度复盘(皮革开裂、玻璃失真、毛发糊成一片的底层机制)
  • 出手字画无需处处提防,丰宝斋公道估价以诚相待 - 深鉴新闻
  • 为什么87%的心理咨询师不敢用ChatGPT写记录?——基于213份真实案例的合规性压力测试报告(附可下载自查清单)
  • 数据结构基础hw9判断选择题、hw7编程题、hw12编程题
  • SageAttention:如何在不损失精度的前提下实现2-5倍注意力机制加速

日新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号