五大基础算法——分治算法
分治算法 是一种通过将问题分解为多个规模较小的子问题,递归解决子问题,然后将子问题的解合并为原问题解的算法思想。它通常包含三个步骤:分解(Divide)、解决(Conquer) 和 合并(Combine)。以下是分治算法的核心概念、适用场景、实现方法及经典例题:
一、核心概念
- 分解(Divide)
- 将原问题分解为若干个规模较小的子问题。
- 解决(Conquer)
- 递归解决子问题。如果子问题规模足够小,则直接求解。
- 合并(Combine)
- 将子问题的解合并为原问题的解。
二、适用场景
- 排序算法
- 如归并排序、快速排序。
- 查找算法
- 如二分查找。
- 数学问题
- 如大整数乘法、矩阵乘法(Strassen算法)。
- 数据结构操作
- 如最近点对问题、最大子数组问题。
三、实现步骤
- 分解问题
- 将原问题分解为若干个规模较小的子问题。
- 递归求解
- 对每个子问题递归调用分治算法。
- 合并结果
- 将子问题的解合并为原问题的解。
四、经典例题与代码
1. 归并排序
问题描述:将一个无序数组排序。
def mergeSort(arr):if len(arr) <= 1: # 基线条件return arrmid = len(arr) // 2left = mergeSort(arr[:mid]) # 分解并递归解决左半部分right = mergeSort(arr[mid:]) # 分解并递归解决右半部分return merge(left, right) # 合并左右部分def merge(left, right):result = []i = j = 0while i < len(left) and j < len(right):if left[i] < right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result.extend(left[i:])result.extend(right[j:])return result# 示例
arr = [38, 27, 43, 3, 9, 82, 10]
print(mergeSort(arr)) # 输出 [3, 9, 10, 27, 38, 43, 82]
2. 快速排序
问题描述:将一个无序数组排序。
def quickSort(arr):if len(arr) <= 1: # 基线条件return arrpivot = arr[len(arr) // 2] # 选择基准值left = [x for x in arr if x < pivot] # 分解为小于基准值的子问题middle = [x for x in arr if x == pivot] # 分解为等于基准值的子问题right = [x for x in arr if x > pivot] # 分解为大于基准值的子问题return quickSort(left) + middle + quickSort(right) # 递归解决并合并# 示例
arr = [38, 27, 43, 3, 9, 82, 10]
print(quickSort(arr)) # 输出 [3, 9, 10, 27, 38, 43, 82]
3. 二分查找
问题描述:在有序数组中查找目标值。
def binarySearch(arr, target):if not arr: # 基线条件return -1mid = len(arr) // 2if arr[mid] == target:return midelif arr[mid] < target:result = binarySearch(arr[mid+1:], target)return result + mid + 1 if result != -1 else -1else:return binarySearch(arr[:mid], target)# 示例
arr = [1, 3, 5, 7, 9]
print(binarySearch(arr, 5)) # 输出 2
4. 最大子数组问题
问题描述:找到一个数组中具有最大和的连续子数组。
def maxSubArray(nums):def divideAndConquer(left, right):if left == right: # 基线条件return nums[left]mid = (left + right) // 2# 递归解决左半部分和右半部分left_max = divideAndConquer(left, mid)right_max = divideAndConquer(mid+1, right)# 计算跨越中点的最大子数组和cross_max = maxCrossingSum(left, mid, right)return max(left_max, right_max, cross_max)def maxCrossingSum(left, mid, right):left_sum = float('-inf')current_sum = 0for i in range(mid, left-1, -1):current_sum += nums[i]left_sum = max(left_sum, current_sum)right_sum = float('-inf')current_sum = 0for i in range(mid+1, right+1):current_sum += nums[i]right_sum = max(right_sum, current_sum)return left_sum + right_sumreturn divideAndConquer(0, len(nums)-1)# 示例
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
print(maxSubArray(nums)) # 输出 6
五、分治算法的优缺点
优点
- 问题分解清晰
- 将复杂问题分解为简单子问题,易于理解和实现。
- 适合并行计算
- 子问题通常相互独立,适合并行处理。
- 高效解决复杂问题
- 如排序、查找、数学计算等问题。
缺点
- 递归开销
- 递归调用可能导致栈溢出或额外开销。
- 子问题重叠
- 子问题可能重复计算,需结合动态规划优化。
- 实现复杂度高
- 某些问题的分解和合并逻辑较复杂。
六、适用问题特征
- 问题可以分解为多个独立的子问题。
- 子问题的解可以合并为原问题的解。
- 常见问题包括:排序、查找、数学计算、数据结构操作等。
分治算法是一种强大的工具,适合解决复杂问题。在实际应用中,需注意子问题的独立性和合并逻辑,必要时结合其他算法(如动态规划)进行优化。
相关文章:
五大基础算法——分治算法
分治算法 是一种通过将问题分解为多个规模较小的子问题,递归解决子问题,然后将子问题的解合并为原问题解的算法思想。它通常包含三个步骤:分解(Divide)、解决(Conquer) 和 合并(Comb…...
HarmonyOS NEXT 声明式UI语法学习笔记-创建自定义组件
基础语法概述 ArkTS的基本组成 装饰器:用于装饰类、结构、方法以及变量,并赋予其特殊含义。如上图都是装饰器,Component表示自定义组件,Entry表示表示自定义组件的入口组件,State表示组件中的状态变量,当状…...
补充二分LIS
B3637 最长上升子序列 题目描述 这是一个简单的动规板子题。 给出一个由 n ( n ≤ 5000 ) n(n\le 5000) n(n≤5000) 个不超过 1 0 6 10^6 106 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。 最长上升子序列是指,从原序列中按顺序取出一些数字排…...
用户模块——握手验证
1. 引言 在现代 Web 应用中,WebSocket 以其全双工通信、低延迟、减少 HTTP 开销等优势,被广泛应用于即时通讯、在线游戏、实时数据推送等场景。然而,在涉及用户认证时,WebSocket 存在一个常见问题——每次刷新页面都会重新建立 We…...
97.HarmonyOS NEXT跑马灯组件教程:基础概念与架构设计
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT跑马灯组件教程:基础概念与架构设计 1. 跑马灯组件概述 跑马灯(Marquee)是一种常见的UI组件&a…...
81.HarmonyOS NEXT 状态管理与响应式编程:@Observed深度解析
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT 状态管理与响应式编程:Observed深度解析 文章目录 HarmonyOS NEXT 状态管理与响应式编程:Observed深度解析…...
【Agent】OpenManus-Agent架构详细分析
各组件详细设计见: BaseAgent:BaseAgentReActAgent:ReActAgentToolCallAgent:ToolCallAgent具体Agent实现:具体AgentMemory数据结构:Memory 1. 智能体层次结构 OpenManus 采用了一个多层次的智能体继承结…...
股指期货有卖不出去的时候吗?
在股指期货的交易世界里,很多人都有这样的疑问:股指期货会不会有卖不出去的时候呢?答案是会的,下面咱们就来详细唠唠为啥会出现这种情况。 市场极端行情下难以卖出 1.跌停限制:股指期货和股票一样,也有涨…...
前端Html5 Canvas面试题及参考答案
目录 Canvas 元素的默认尺寸是多少?如何正确设置其宽高以避免图像拉伸? 如何获取 Canvas 的 2D 上下文对象?3D 上下文支持哪些技术? canvas.width 与 canvas.style.width 的区别是什么? Canvas 支持的图像格式有哪些?如何将 Canvas 转换为 Base64 图片? Canvas 中如…...
【ES6】03-Set + Map
本文介绍两种集合 set map 的操作和方法。 目录 1. Set 1.1 set基本使用 1.2 add 1.3 delete 1.4 has 1.5 size 1.6 set转换为数组 1.7 拓展运算符 1.8 for...of 1.9 forEach 1.10 set给数组去重 2. Map 2.1 创建map集合 2.2 set添加元素 2.3 delete删除元素 …...
Java缓存String(字符串常量池)、Integer (-128 到 127 )
对问题的解释 1. “字符串常量池存储的是string对象的直接引用,而不是直接存放的对象,是一张string table” 的含义 这句话可以从以下几个方面理解: (1) 字符串常量池的存储内容 直接引用:字符串常量池中存储的是指向实际 Stri…...
消息队列的特性与使用场景:Kafka、ActiveMQ、RabbitMQ与RocketMQ的深度剖析
在分布式系统和微服务架构中,消息队列是实现服务间通信和解耦的核心组件。Kafka、ActiveMQ、RabbitMQ和RocketMQ是当前最受欢迎的消息队列解决方案,它们各自具有独特的特性和适用场景。本文将从特性和使用场景两个维度进行对比分析,帮助读者更…...
开发、科研、日常办公工具汇总(自用,持续更新)
主要记录汇总一下自己平常会用到的网站工具,方便查阅。 update:2025/2/11(开发网站补一下) update:2025/2/21(补充一些AI工具,刚好在做AI视频相关工作) update:2025/3/7&…...
解决VueI18n使用浏览器插件翻译后,切换国际化失效的问题
问题复现 在使用Vue-i18n对页面进行国际化的时候,使用浏览器翻译插件(如腾讯翻译)后,切换国际化语言,随后当我们关闭浏览器翻译插件后,再次切换国际化语言,原来被翻译的文字无法正确切换 出现…...
HTML5 drag API实现列表拖拽排序
拖拽API(Drag and Drop API)是HTML5提供的一组功能,使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能,用户可以通过鼠标将元素拖动并放置到指定的目标区域。 事件类型 dragstart࿱…...
改变一生的思维模型【11】升维
升维思维模型:突破认知局限的破局法则 一、定义与核心逻辑 升维思维是通过增加分析维度,将问题投射到更高认知层次寻找解决方案的思考方式。其本质是跳出原有竞争维度,在更广阔的空间重构游戏规则。核心逻辑在于:当低维战场陷入…...
【动手学深度学习】#2线性神经网络
主要参考学习资料: 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 2.1 线性回归2.1.1 线性回归的基本元素线性模型损失函数解析解随机梯度下降 2.1.3 最大似然估计 2.2 线性回归从零开始实现2.2.1 生成数据集2.2.2 读取数…...
计算机网络——NAT
一、什么是NAT? NAT(Network Address Translation,网络地址转换) 是一种将 私有IP地址 与 公有IP地址 相互映射的技术,主要用于解决IPv4地址不足的问题。它像一名“翻译官”,在数据包经过路由器或防火墙时…...
Stable Deffusion--常见模型插件详解
1.Checkpoint大模型 Checkpoint 是生成图像的基础模型,决定了整体画风如动漫、写实、机甲等。它是必选项,所有图像生成必须基于一个主模型。文件体积较大通常 1.5GB 以上,格式为 .ckpt 或 .safetensors。 存放位置为:\models\Sta…...
防重复提交详解:从前端Vue到后端Java的全面解决方案
防重复提交详解:从前端Vue到后端Java的全面解决方案 一、重复提交问题概述 在Web应用开发中,表单重复提交是一个常见问题,可能导致: 数据库中出现重复记录重复执行业务逻辑(如多次扣款)系统资源浪费用户…...
同一子网通信
添加交换机后的通信流程 1. 同一子网内(使用交换机) 判断是否在同一子网: 主机A通过子网掩码判断主机B的IP地址是否属于同一子网。若在同一子网,主机A需要通过ARP获取主机B的MAC地址。 ARP请求(广播)&…...
快速迭代:利用 nodemon 和其他工具实现 Express.js 热更新
在开发 Express.js 应用时,热更新(Hot Reloading)可以显著提升开发效率,因为它允许你在修改代码后立即看到效果,而无需手动重启服务器。以下是几种实现热更新的方法和工具,帮助你在开发过程中更高效地工作。…...
BUG日志:Maven项目启动报错(文件名或者文件扩展名过长)
Bug日志编号:[Maven-001] 标题:Windows系统下Maven项目因路径过长导致命令行执行失败 1. 问题描述 现象:执行mvn clean install时报错: The input line is too long 或 The filename or extension is too long触发条件…...
IntelliJ IDEA 快捷键系列:重命名快捷键详解
目录 引言一、默认重命名快捷键1. Windows 系统2. Mac 系统 二、操作步骤与技巧1. 精准选择重命名范围2. 智能过滤无关内容 三、总结 引言 在代码重构中,重命名变量、类、方法 是最常用的操作之一。正确使用快捷键可以极大提升开发效率。本文针对 Ma…...
零基础掌握分布式ID生成:从理论到实战的完整指南 [特殊字符]
一、为什么需要分布式ID? 🤔 在单机系统中,使用数据库自增ID就能满足需求。但在分布式系统中,多个服务节点同时生成ID时会出现以下问题: ID冲突:不同节点生成相同ID 扩展困难:数据库自增ID无法…...
使用python反射,实现pytest读取yaml并发送请求
pytest yaml yaml - feature: 用户模块story: 登录title: 添加用户request:method: POSTurl: /system/user/listheaders: nullparams: nullvalidate: nullread_yaml_all def read_yaml_all(path):with open(path, r, encodingutf-8) as f:value yaml.safe_load(f)return v…...
点灯、点各式各样的灯
鱼离水则身枯,心离书则神索。 前言闪灯呼吸灯流水灯二进制数显示灯蜂鸣器节拍流水音乐会总结 前言 上回书咱们简单了解了一点有关特殊功能寄存器sfr、通用输入输出GPIO、位操作运算符sbit和一个不靠单片机上的晶振(拿来定时的)的依托于单片机CPU空操作的ms级延时函…...
Matlab 汽车悬架系统动力学建模与仿真
1、内容简介 略 Matlab 170-汽车悬架系统动力学建模与仿真 可以交流、咨询、答疑 2、内容说明 略 本文对题目给定的1/2汽车四自由度模型,建立状态空间模型进行系统分析,并通过MATLAB仿真对系统进行稳定性、可控可观测性分析,对得的结果进行…...
专访数势科技谭李:智能分析 Agent 打通数据平权的最后一公里
作者|斗斗 编辑|皮爷 出品|产业家 伦敦塔桥下的泰晤士河底,埋藏着工业革命的隐秘图腾——布鲁内尔设计的隧道盾构机。在19世纪城市地下轨道建设的过程中,这个直径11米的钢铁巨兽没有选择拓宽河道,而是开创了地下通行的新维度。 “我们不…...
了解浏览器
本文来自腾讯元宝 Chrome浏览器(Google Chrome)是由Google开发的一款免费网页浏览器,自2008年发布以来凭借其高效、安全、简洁的特点成为全球市场份额最高的浏览器。以下是其核心信息及最新动态的综合分析: 一、核心优势与技术特点…...
