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

【CS.AL】算法核心之分治算法:从入门到进阶

文章目录

    • 1. 概述
    • 2. 适用场景
    • 3. 设计步骤
    • 4. 优缺点
    • 5. 典型应用
    • 6. 题目和代码示例
      • 6.1 简单题目:归并排序
      • 6.2 中等题目:最近点对问题
      • 6.3 困难题目:分数背包问题
    • 7. 题目和思路表格
    • 8. 总结
    • References

1000.01.CS.AL.1.4-核心-DivedeToConquerAlgorithm-Created: 2024-06-15.Saturday09:35
在这里插入图片描述

1. 概述

分治算法(Divide and Conquer)是一种重要的算法设计思想,其核心思想是将一个复杂的问题分解为多个相对简单的小问题,通过解决这些小问题再合并其结果,从而得到原问题的解。分治算法的典型特征是递归,常用于求解具有重复子问题性质的问题。

2. 适用场景

分治算法适用于以下场景:

  • 问题可以分解为若干个规模较小且相互独立的子问题。
  • 这些子问题的解可以合并得到原问题的解。
  • 具有最优子结构性质,即子问题的最优解可以合成原问题的最优解。

3. 设计步骤

  1. 分解(Divide):将原问题分解为若干个子问题,这些子问题的结构与原问题相同但规模较小。
  2. 解决(Conquer):递归地解决这些子问题。当子问题的规模足够小时,直接解决。
  3. 合并(Combine):将子问题的解合并,得到原问题的解。

4. 优缺点

  • 优点:分治算法的递归思想使其在解决许多复杂问题时表现出色。具有良好的可扩展性和并行计算的潜力。
  • 缺点:对于某些问题,分治算法可能会引入额外的开销,如递归调用栈和合并步骤的时间复杂度。

5. 典型应用

  • 归并排序(Merge Sort):一种高效的排序算法,利用分治思想将数组分为两半,递归地排序并合并。
  • 快速排序(Quick Sort):另一种高效的排序算法,选择一个基准元素,将数组分为两部分,递归排序。
  • 最近点对问题(Closest Pair Problem):在平面上找到距离最近的两点,分治法可以将时间复杂度降至 O(nlog⁡n)O(n \log n)O(nlogn)。
  • 矩阵乘法(Strassen’s Algorithm):一种用于矩阵乘法的分治算法,降低了时间复杂度。

6. 题目和代码示例

6.1 简单题目:归并排序

题目描述:实现归并排序算法,对给定的数组进行排序。

代码示例

#include <iostream>
#include <vector>// 函数声明
void mergeSort(std::vector<int>& arr, int left, int right);
void merge(std::vector<int>& arr, int left, int mid, int right);int main() {std::vector<int> arr = {38, 27, 43, 3, 9, 82, 10};mergeSort(arr, 0, arr.size() - 1);for (int num : arr) {std::cout << num << " ";}std::cout << std::endl;return 0;
}// 归并排序:递归地将数组分成两半进行排序
void mergeSort(std::vector<int>& arr, int left, int right) {if (left < right) {int mid = left + (right - left) / 2;mergeSort(arr, left, mid);mergeSort(arr, mid + 1, right);merge(arr, left, mid, right);}
}// 合并两个已排序的子数组
void merge(std::vector<int>& arr, int left, int mid, int right) {int n1 = mid - left + 1;int n2 = right - mid;std::vector<int> L(n1), R(n2);for (int i = 0; i < n1; ++i) {L[i] = arr[left + i];}for (int j = 0; j < n2; ++j) {R[j] = arr[mid + 1 + j];}int i = 0, j = 0, k = left;while (i < n1 && j < n2) {if (L[i] <= R[j]) {arr[k] = L[i++];} else {arr[k] = R[j++];}++k;}while (i < n1) {arr[k++] = L[i++];}while (j < n2) {arr[k++] = R[j++];}
}

Others.

def merge_sort(arr):if len(arr) > 1:mid = len(arr) // 2left_half = arr[:mid]right_half = arr[mid:]merge_sort(left_half)merge_sort(right_half)i = j = k = 0while i < len(left_half) and j < len(right_half):if left_half[i] < right_half[j]:arr[k] = left_half[i]i += 1else:arr[k] = right_half[j]j += 1k += 1while i < len(left_half):arr[k] = left_half[i]i += 1k += 1while j < len(right_half):arr[k] = right_half[j]j += 1k += 1# 示例
arr = [38, 27, 43, 3, 9, 82, 10]
merge_sort(arr)
print(arr)  # 输出: [3, 9, 10, 27, 38, 43, 82]

6.2 中等题目:最近点对问题

题目描述:在平面上找到距离最近的两点,时间复杂度为 O(nlog⁡n)。

代码示例

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>struct Point {int x, y;
};double dist(const Point& p1, const Point& p2) {return std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}double closestPair(std::vector<Point>& points, int left, int right) {if (right - left <= 3) {double minDist = std::numeric_limits<double>::infinity();for (int i = left; i < right; ++i) {for (int j = i + 1; j <= right; ++j) {minDist = std::min(minDist, dist(points[i], points[j]));}}return minDist;}int mid = left + (right - left) / 2;double d1 = closestPair(points, left, mid);double d2 = closestPair(points, mid + 1, right);double d = std::min(d1, d2);std::vector<Point> strip;for (int i = left; i <= right; ++i) {if (std::abs(points[i].x - points[mid].x) < d) {strip.push_back(points[i]);}}std::sort(strip.begin(), strip.end(), [](const Point& p1, const Point& p2) {return p1.y < p2.y;});double minDist = d;for (size_t i = 0; i < strip.size(); ++i) {for (size_t j = i + 1; j < strip.size() && (strip[j].y - strip[i].y) < minDist; ++j) {minDist = std::min(minDist, dist(strip[i], strip[j]));}}return minDist;
}int main() {std::vector<Point> points = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4}};std::sort(points.begin(), points.end(), [](const Point& p1, const Point& p2) {return p1.x < p2.x;});std::cout << "最近点对距离: " << closestPair(points, 0, points.size() - 1) << std::endl;return 0;
}

Others.

import mathdef dist(p1, p2):return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)def closest_pair(points):def closest_pair_recursive(points):if len(points) <= 3:return min((dist(p1, p2), (p1, p2)) for i, p1 in enumerate(points) for p2 in points[i+1:])[1]mid = len(points) // 2left_half = points[:mid]right_half = points[mid:](d1, pair1) = closest_pair_recursive(left_half)(d2, pair2) = closest_pair_recursive(right_half)d = min(d1, d2)pair = pair1 if d1 < d2 else pair2strip = [p for p in points if abs(p[0] - points[mid][0]) < d]strip.sort(key=lambda p: p[1])for i in range(len(strip)):for j in range(i+1, len(strip)):if strip[j][1] - strip[i][1] >= d:breakd_new = dist(strip[i], strip[j])if d_new < d:d = d_newpair = (strip[i], strip[j])return d, pairpoints.sort(key=lambda p: p[0])return closest_pair_recursive(points)[1]# 示例
points = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]
print(closest_pair(points))  # 输出: ((2, 3), (3, 4))

6.3 困难题目:分数背包问题

题目描述:给定物品的重量和价值,求在背包容量限制下的最大价值,物品可以分割。

代码示例

#include <iostream>
#include <vector>
#include <algorithm>struct Item {double value;double weight;
};double fractionalKnapsack(std::vector<Item>& items, double capacity) {std::sort(items.begin(), items.end(), [](const Item& a, const Item& b) {return (a.value / a.weight) > (b.value / b.weight);});double totalValue = 0;for (const auto& item : items) {if (capacity >= item.weight) {capacity -= item.weight;totalValue += item.value;} else {totalValue += item.value * (capacity / item.weight);break;}}return totalValue;
}int main() {std::vector<Item> items = {{60, 10}, {100, 20}, {120, 30}};double capacity = 50;std::cout << "背包的最大价值: " << fractionalKnapsack(items, capacity) << std::endl;return 0;
}

Others.

def fractional_knapsack(values, weights, capacity):items = list(zip(values, weights))items.sort(key=lambda x: x[0] / x[1], reverse=True)total_value = 0for value, weight in items:if capacity >= weight:capacity -= weighttotal_value += valueelse:total_value += value * (capacity / weight)breakreturn total_value# 示例
values = [60, 100, 120]
weights = [10, 20, 30]
capacity = 50
print(fractional_knapsack(values, weights, capacity))  # 输出: 240.0

7. 题目和思路表格

序号题目题目描述分治策略代码实现
1归并排序对给定的数组进行排序递归地将数组分成两半进行排序代码
2最近点对问题找到距离最近的两点将点集合递归地分成两半代码
3分数背包问题求在背包容量限制下的最大价值每次选择单位重量价值最高的物品代码
4快速排序高效排序算法选择一个基准元素,将数组分为两部分,递归排序代码
5矩阵乘法用于矩阵乘法将矩阵分成更小的子矩阵,递归计算-
6求逆序对数量统计数组中的逆序对个数使用分治法将数组分成两半,递归统计逆序对-
7最大子序和找出最大和的连续子序列将序列递归地分成两半,合并子序列的结果-
8大整数乘法实现高效的大整数乘法使用Karatsuba算法,将大整数分成两部分进行递归计算-
9二维平面上的最近点对在平面上找到距离最近的两点将点集合递归地分成两半,合并结果-
10棋盘覆盖问题用L型骨牌覆盖2^n * 2^n的棋盘将棋盘递归地分成四部分,覆盖部分棋盘-

8. 总结

分治算法是一种强大的算法设计思想,能够高效地解决许多复杂的问题。通过将问题分解为更小的子问题,分治算法不仅能够降低时间复杂度,还具有良好的可扩展性。在实际应用中,理解和掌握分治算法的思想和典型应用,对于解决各种问题具有重要意义。通过本文的例子和思路,相信读者能够深入理解分治算法的关键概念,并灵活应用于实际问题中。

References

相关文章:

【CS.AL】算法核心之分治算法:从入门到进阶

文章目录 1. 概述2. 适用场景3. 设计步骤4. 优缺点5. 典型应用6. 题目和代码示例6.1 简单题目&#xff1a;归并排序6.2 中等题目&#xff1a;最近点对问题6.3 困难题目&#xff1a;分数背包问题 7. 题目和思路表格8. 总结References 1000.01.CS.AL.1.4-核心-DivedeToConquerAlg…...

leetcode刷题记录:hot100强化训练2:二叉树+图论

二叉树 36. 二叉树的中序遍历 递归就不写了&#xff0c;写一下迭代法 class Solution(object):def inorderTraversal(self, root):""":type root: TreeNode:rtype: List[int]"""if not root:return res []cur rootstack []while cur or st…...

湘潭大学信息与网络安全复习笔记2(总览)

前面的实验和作业反正已经结束了&#xff0c;现在就是集中火力把剩下的内容复习一遍&#xff0c;这一篇博客的内容主要是参考教学大纲和教学日历 文章目录 教学日历教学大纲 教学日历 总共 12 次课&#xff0c;第一次课是概述&#xff0c;第二次和第三次课是密码学基础&#x…...

C语言:头歌使用函数找出数组中的最大值

任务描述 本关任务&#xff1a;本题要求实现一个找出整型数组中最大值的函数。 函数接口定义&#xff1a; int FindArrayMax( int a[], int n ); 其中a是用户传入的数组&#xff0c;n是数组a中元素的个数。函数返回数组a中的最大值。 主程序样例: #include <stdio.h>#…...

【技巧】Leetcode 191. 位1的个数【简单】

位1的个数 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回其二进制表达式中 设置位 的个数&#xff08;也被称为汉明重量&#xff09;。 示例 1&#xff1a; 输入&#xff1a;n 11 输出&#xff1a;3 解释&#x…...

【Pandas驯化-02】pd.read_csv读取中文出现error解决方法

【Pandas】驯化-02pd.read_csv读取中文出现error解决方法 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 相关内容文档获取 微信公众号 &…...

linux下C语言如何操作文件(三)

我们继续介绍file_util.c中的函数: bool create_dir(const char* path):创建目录,根据给定的path创建目录,成功返回true,否则返回false。如果有父目录不存在,该函数不会创建。 /*** 创建目录* @param path 目录路径* @return true 创建成功,false 创建失败*/ bool cre…...

6.14作业

使用手动连接&#xff0c;将登录框中的取消按钮使用第二中连接方式&#xff0c;右击转到槽&#xff0c;在该槽函数中&#xff0c;调用关闭函数 将登录按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0…...

MySQL数据库管理(一)

目录 1.MySQL数据库管理 1.1 常用的数据类型​编辑 1.2 char和varchar区别 2. 增删改查命令操作 2.1 查看数据库结构 2.2 SQL语言 2.3 创建及删除数据库和表 2.4 管理表中的数据记录 2.5 修改表名和表结构 3.MySQL的6大约束属性 1.MySQL数据库管理 1.1 常用的数据类…...

Kafka使用教程和案例详解

Kafka 使用教程和案例详解 Kafka 使用教程和案例详解1. Kafka 基本概念1.1 Kafka 是什么?1.2 核心组件2. Kafka 安装与配置2.1 安装 Kafka使用包管理器(如 yum)安装使用 Docker 安装2.2 配置 Kafka2.3 启动 Kafka3. Kafka 使用教程3.1 创建主题3.2 生产消息3.3 消费消息3.4 …...

TGI模型- 同期群-评论文本

用户偏好分析 TGI 1.1 用户偏好分析介绍 要分析的目标&#xff0c;在目标群体中的均值 和 全部群体里的均值进行比较&#xff0c; 差的越多说明 目标群体偏好越明显 TGI&#xff08;Target Group Index&#xff0c;目标群体指数&#xff09;用于反映目标群体在特定研究范围内…...

ESP32 BLE学习(0) — 基础架构

前言 &#xff08;1&#xff09;学习本文之前&#xff0c;需要先了解一下蓝牙的基本概念&#xff1a;BLE学习笔记&#xff08;0.0&#xff09; —— 基础概念&#xff08;0&#xff09; &#xff08;2&#xff09; 学习一款芯片的蓝牙肯定需要先简单了解一下该芯片的体系结构&a…...

【JAVA】Java中Spring Boot如何设置全局的BusinessException

文章目录 前言一、函数解释二、代码实现三、总结 前言 在Java应用开发中&#xff0c;我们常常需要读取配置文件。Spring Boot提供了一种方便的方式来读取配置。在本文中&#xff0c;我们将探讨如何在Spring Boot中使用Value和ConfigurationProperties注解来读取配置。 一、函数…...

pdf.js实现web h5预览pdf文件(兼容低版本浏览器)

注意 使用的是pdf.js 版本为 v2.16.105。因为新版本 兼容性不太好&#xff0c;部分手机预览不了&#xff0c;所以采用v2版本。 相关依赖 "canvas": "^2.11.2", "pdfjs-dist": "^2.16.105", "core-js-pure": "^3.37.…...

SSID简介

一、 SSID 概念定义 SSID&#xff08;Service Set Identifier&#xff09;即服务集标识符。它是无线网络中的一个重要标识&#xff0c;用于区分不同的无线网络。 相当于无线网络的名称&#xff0c;用于区分不同的无线网络。用户在众多可用网络中识别和选择特定网络的依据。通…...

PS通过GTX实现SFP网络通信1

将 PS ENET1 的 GMII 接口和 MDIO 接口 通过 EMIO 方 式引出。在 PL 端将引出的 GMII 接口和 MDIO 接口与 IP 核 1G/2.5G Ethernet PCS/PMA or SGMII 连接&#xff0c; 1G/2.5G Ethernet PCS/PMA or SGMII 通过高速串行收发器 GTX 与 MIZ7035/7100 开发…...

前端面试项目细节重难点(已工作|做分享)(九)

面试官&#xff1a;请你讲讲你在工作中如何开发一个新需求&#xff0c;你的整个开发过程是什么样的&#xff1f; 答&#xff1a;仔细想想&#xff0c;我开发新需求的过程如下&#xff1a; &#xff08;1&#xff09;第一步&#xff1a;理解需求文档&#xff1a; 首先&#x…...

区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测

区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测 目录 区间预测 | Matlab实现BP-ABKDE的BP神经网络自适应带宽核密度估计多变量回归区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现BP-ABKDE的BP神经网络自适应带…...

抢占人工智能行业红利,前阿里巴巴产品专家带你15天入门AI产品经理

前言 当互联网行业巨头纷纷布局人工智能&#xff0c;国家将人工智能上升为国家战略&#xff0c;藤校核心课程涉足人工智能…人工智能领域蕴含着巨大潜力&#xff0c;早已成为业内共识。 面对极大的行业空缺&#xff0c;不少人都希望能抢占行业红利期&#xff0c;进入AI领域。…...

MEMS:Lecture 16 Gyros

陀螺仪原理 A classic spinning gyroscope measures the rotation rate by utilizing the conservation of angular momentum. 经典旋转陀螺仪通过利用角动量守恒来测量旋转速率。 Coriolis Effect and Coriolis Force 科里奥利效应是一种出现在旋转参考系中的现象。它描述了…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...

Axure 下拉框联动

实现选省、选完省之后选对应省份下的市区...

2.3 物理层设备

在这个视频中&#xff0c;我们要学习工作在物理层的两种网络设备&#xff0c;分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间&#xff0c;需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质&#xff0c;假设A节点要给…...

CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?

在现代前端开发中&#xff0c;Utility-First (功能优先) CSS 框架已经成为主流。其中&#xff0c;Tailwind CSS 无疑是市场的领导者和标杆。然而&#xff0c;一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...