随机算法一文深度全解
随机算法一文深度全解
- 一、随机算法基础
- 1.1 定义与核心特性
- 1.2 算法优势与局限
- 二、随机算法经典案例
- 2.1 随机化快速排序
- 原理推导
- 问题分析与策略
- 代码实现(Python、Java、C++)
- 2.2 蒙特卡罗方法计算 π 值
- 原理推导
- 问题分析与策略
- 代码实现(Python、Java、C++)
- 2.3 拉斯维加斯算法求解八皇后问题
- 原理推导
- 问题分析与策略
- 代码实现(Python、Java、C++);
- 三、随机算法性能与应用
- 3.1 性能评估
- 3.2 应用场景
随机算法凭借独特的随机决策机制,为复杂问题提供高效解决方案。本文我将围绕三种核心随机算法、并引入问题剖析与多语言实现展开,帮你全面掌握这一重要算法。
一、随机算法基础
1.1 定义与核心特性
随机算法在运行中引入随机因素辅助决策,其结果具有不确定性。按特性可分为:
-
拉斯维加斯算法:结果必正确,但耗时不定
-
蒙特卡罗算法:限时结束,结果有错误概率
-
舍伍德算法:均衡算法性能,避免最坏情况
1.2 算法优势与局限
优势
: 高效求解复杂问题、实现简单;
局限
: 结果不确定、理论分析复杂,在金融计算等重要场景需谨慎使用。
二、随机算法经典案例
2.1 随机化快速排序
原理推导
快速排序的核心思想是分治法,通过选定一个枢轴元素,将数组划分为两部分:小于枢轴的元素组成左子数组,大于枢轴的元素组成右子数组,然后递归地对这两个子数组进行排序。在传统快速排序中,如果枢轴选择不当,例如数组已经有序时,每次都选择第一个或最后一个元素作为枢轴,会导致划分极不均衡,时间复杂度退化为 O ( n 2 ) O(n^2) O(n2)。
随机化快速排序为解决这一问题,在每次划分前随机选择枢轴元素。假设数组长度为 n n n,随机选择枢轴的过程可以看作从 n n n 个元素中任选一个,每个元素被选中的概率均为 1 n \frac{1}{n} n1。
设 T ( n ) T(n) T(n) 为随机化快速排序对长度为 n n n 的数组进行排序的时间复杂度。对于一次划分操作,随机选择的枢轴将数组划分为两部分,左子数组长度为 k k k,右子数组长度为 n − k − 1 n - k - 1 n−k−1( k k k 的取值范围是 0 0 0 到 n − 1 n - 1 n−1),则有:
T ( n ) = O ( n ) + 1 n ∑ k = 0 n − 1 ( T ( k ) + T ( n − k − 1 ) ) T(n) = O(n) + \frac{1}{n}\sum_{k = 0}^{n - 1}(T(k) + T(n - k - 1)) T(n)=O(n)+n1∑k=0n−1(T(k)+T(n−k−1))
其中 O ( n ) O(n) O(n) 是划分操作的时间复杂度,即遍历一次数组将元素分到左右子数组的时间。通过数学推导(利用数学归纳法等),可以证明随机化快速排序的平均时间复杂度为 O ( n log n ) O(n \log n) O(nlogn)。
在最坏情况下,即使是随机选择枢轴,也有可能每次都选到数组中的最大值或最小值,导致划分不均衡,此时时间复杂度退化为 O ( n 2 ) O(n^2) O(n2),但这种情况发生的概率极小。
问题分析与策略
-
问题:随机化快速排序虽然平均性能良好,但在最坏情况下时间复杂度退化,并且随机数生成操作会带来一定的额外开销。
-
应对策略:在实际应用中,可以结合其他排序算法(如插入排序),当数组规模较小时,使用插入排序代替随机化快速排序,因为插入排序在小规模数据上性能较好,且没有随机数生成开销。同时,在选择随机数生成器时,尽量选择高效的实现,减少额外开销。
代码实现(Python、Java、C++)
Python实现
import randomdef randomized_quicksort(arr):if len(arr) <= 1:return arrpivot = random.choice(arr)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 randomized_quicksort(left) + middle + randomized_quicksort(right)
Java实现
import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class RandomizedQuicksort {public static List<Integer> randomizedQuicksort(List<Integer> arr) {if (arr.size() <= 1) {return arr;}Random random = new Random();int pivot = arr.get(random.nextInt(arr.size()));List<Integer> left = new ArrayList<>();List<Integer> middle = new ArrayList<>();List<Integer> right = new ArrayList<>();for (int num : arr) {if (num < pivot) {left.add(num);} else if (num == pivot) {middle.add(num);} else {right.add(num);}}List<Integer> result = new ArrayList<>();result.addAll(randomizedQuicksort(left));result.addAll(middle);result.addAll(randomizedQuicksort(right));return result;}public static void main(String[] args) {List<Integer> arr = List.of(5, 3, 8, 6, 7);System.out.println(randomizedQuicksort(arr));}
}
C++实现
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;vector<int> randomized_quicksort(vector<int> arr) {if (arr.size() <= 1) {return arr;}srand(time(nullptr));int pivot_index = rand() % arr.size();int pivot = arr[pivot_index];vector<int> left, middle, right;for (int num : arr) {if (num < pivot) {left.push_back(num);} else if (num == pivot) {middle.push_back(num);} else {right.push_back(num);}}vector<int> result;vector<int> sorted_left = randomized_quicksort(left);vector<int> sorted_right = randomized_quicksort(right);result.insert(result.end(), sorted_left.begin(), sorted_left.end());result.insert(result.end(), middle.begin(), middle.end());result.insert(result.end(), sorted_right.begin(), sorted_right.end());return result;
}
2.2 蒙特卡罗方法计算 π 值
原理推导
蒙特卡罗方法基于概率统计原理。在一个边长为 1 的正方形内,嵌入一个半径为 1 的四分之一圆。根据几何图形的面积公式,正方形的面积 S s q u a r e = 1 × 1 = 1 S_{square} = 1 \times 1 = 1 Ssquare=1×1=1,四分之一圆的面积 S c i r c l e = 1 4 π r 2 = π 4 S_{circle} = \frac{1}{4} \pi r^2 = \frac{\pi}{4} Scircle=41πr2=4π(这里 r = 1 r = 1 r=1)。
在正方形内随机生成大量的点,设生成的总点数为 N N N,落在四分之一圆内的点数为 M M M。根据几何概率模型,点落在四分之一圆内的概率 P P P 等于四分之一圆的面积与正方形面积的比值,即 P = S c i r c l e S s q u a r e = π 4 P = \frac{S_{circle}}{S_{square}} = \frac{\pi}{4} P=SsquareScircle=4π。
同时,从统计角度来看,点落在四分之一圆内的概率又可以近似表示为 M N \frac{M}{N} NM,即 P ≈ M N P \approx \frac{M}{N} P≈NM。由此可得:
π 4 ≈ M N \frac{\pi}{4} \approx \frac{M}{N} 4π≈NM
整理后得到:
π ≈ 4 × M N \pi \approx 4 \times \frac{M}{N} π≈4×NM
随着生成点的数量 N N N 不断增加,根据大数定律, M N \frac{M}{N} NM 会越来越接近真实的概率值,从而使得 π \pi π 的估算值越来越准确。
问题分析与策略
-
问题:蒙特卡罗方法计算 π 值的结果存在误差,且误差与生成点的数量相关。在点数量较少时,估算结果可能与真实值相差较大;同时,生成大量随机点会消耗较多的计算资源和时间。
-
应对策略:为了减少误差,可以增加生成点的数量,但这会增加计算时间。在实际应用中,可以根据对精度的要求,选择合适的点数量。此外,还可以采用并行计算的方式,将生成点和统计的任务分配到多个处理器核心上,加快计算速度。同时,利用一些优化的随机数生成算法,提高随机点生成的效率。
代码实现(Python、Java、C++)
Python实现
import randomdef estimate_pi(num_points):inside_circle = 0for _ in range(num_points):x = random.random()y = random.random()if x ** 2 + y ** 2 <= 1:inside_circle += 1return 4 * inside_circle / num_points
Java实现
public class MonteCarloPi {public static double estimatePi(int numPoints) {int insideCircle = 0;for (int i = 0; i < numPoints; i++) {double x = Math.random();double y = Math.random();if (x * x + y * y <= 1) {insideCircle++;}}return 4.0 * insideCircle / numPoints;}public static void main(String[] args) {System.out.println(estimatePi(1000000));}
}
C++实现
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;double estimate_pi(int num_points) {int inside_circle = 0;srand(time(nullptr));for (int i = 0; i < num_points; i++) {double x = static_cast<double>(rand()) / RAND_MAX;double y = static_cast<double>(rand()) / RAND_MAX;if (x * x + y * y <= 1) {inside_circle++;}}return 4.0 * inside_circle / num_points;
}
2.3 拉斯维加斯算法求解八皇后问题
原理推导
八皇后问题要求在一个 8 × 8 8 \times 8 8×8 的棋盘上放置 8 个皇后,使得任意两个皇后都不能互相攻击(即不能在同一行、同一列或同一对角线上)。
拉斯维加斯算法采用随机尝试的策略。首先,棋盘可以用一个长度为 8 的数组表示,数组的下标表示行,数组元素的值表示皇后在该行所在的列。例如,board[3] = 5
表示第 3 行的皇后放置在第 5 列。
算法开始时,从第一行开始,随机选择一列放置皇后,然后检查该放置是否合法,即检查是否与之前已经放置的皇后在同一列或同一对角线上。检查对角线的方法是:对于两个位置 ( i 1 , j 1 ) (i_1, j_1) (i1,j1) 和 ( i 2 , j 2 ) (i_2, j_2) (i2,j2),如果 ∣ i 1 − i 2 ∣ = ∣ j 1 − j 2 ∣ |i_1 - i_2| = |j_1 - j_2| ∣i1−i2∣=∣j1−j2∣,则它们在同一条对角线上。
如果当前放置不合法,则重新随机选择一列放置;如果合法,则继续处理下一行。不断重复这个过程,直到在 8 行都成功放置皇后,即找到一个合法的解;或者达到预设的尝试次数,仍未找到解,则算法结束。
从概率角度分析,每次随机放置皇后时,在某一行找到合法位置的概率会随着已经放置的皇后数量增加而变化。当放置的皇后较少时,找到合法位置的概率相对较大;随着皇后数量增多,棋盘上可放置的位置受限,找到合法位置的概率降低。但只要尝试次数足够多,在理论上是有可能找到解的。
问题分析与策略
-
问题:拉斯维加斯算法求解八皇后问题可能存在找不到解的情况(当尝试次数达到上限时),并且随机放置的策略可能导致算法在很长时间内都无法找到解,效率较低。
-
应对策略:可以通过增加尝试次数来提高找到解的概率,但这会增加算法的运行时间。为了提高效率,可以结合一些启发式策略,例如在随机选择列时,优先选择冲突可能性较小的列。比如,统计每列目前受到攻击的情况,优先选择受攻击次数少的列放置皇后,这样可以减少无效尝试,加快找到解的速度。
代码实现(Python、Java、C++);
Python实现
import randomdef is_safe(board, row, col):for r in range(row):if board[r] == col or abs(row - r) == abs(col - board[r]):return Falsereturn Truedef solve_eight_queens():board = [-1] * 8attempts = 1000for _ in range(attempts):for row in range(8):col = random.randint(0, 7)if is_safe(board, row, col):board[row] = colelse:breakelse:return boardreturn None
Java实现
import java.util.Random;public class LasVegasEightQueens {public static int[] solveEightQueens() {int[] board = new int[8];int attempts = 1000;Random random = new Random();for (int attempt = 0; attempt < attempts; attempt++) {for (int row = 0; row < 8; row++) {int col = random.nextInt(8);if (isSafe(board, row, col)) {board[row] = col;} else {break;}}if (isSolution(board)) {return board;}}return null;}private static boolean isSafe(int[] board, int row, int col) {for (int r = 0; r < row; r++) {if (board[r] == col || Math.abs(row - r) == Math.abs(col - board[r])) {return false;}}return true;}private static boolean isSolution(int[] board) {for (int row = 0; row < 8; row++) {if (!isSafe(board, row, board[row])) {return false;}}return true;}public static void main(String[] args) {int[] solution = solveEightQueens();if (solution != null) {for (int col : solution) {System.out.print(col + " ");}} else {System.out.println("未找到解");}}
}
C++实现
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace std;bool is_safe(vector<int> board, int row, int col) {for (int r = 0; r < row; r++) {if (board[r] == col || abs(row - r) == abs(col - board[r])) {return false;}}return true;
}vector<int> solve_eight_queens() {vector<int> board(8, -1);int attempts = 1000;srand(time(nullptr));for (int _ = 0; _ < attempts; _++) {for (int row = 0; row < 8; row++) {int col = rand() % 8;if (is_safe(board, row, col)) {board[row] = col;} else {break;}}if (board[7] != -1) {return board;}}return vector<int>();
}
三、随机算法性能与应用
3.1 性能评估
时间复杂度需考虑平均与最坏情况;空间复杂度关注额外空间占用;蒙特卡罗算法还需分析误差范围。
3.2 应用场景
在密码学用于密钥生成;机器学习中用于随机梯度下降优化模型;分布式系统里,实现负载均衡与任务调度。此外,在图像渲染、路径规划等领域,随机算法也发挥着作用。
That’s all, thanks for reading!
觉得有用就点个赞
、收进收藏
夹吧!关注
我,获取更多干货~
相关文章:

随机算法一文深度全解
随机算法一文深度全解 一、随机算法基础1.1 定义与核心特性1.2 算法优势与局限 二、随机算法经典案例2.1 随机化快速排序原理推导问题分析与策略代码实现(Python、Java、C) 2.2 蒙特卡罗方法计算 π 值原理推导问题分析与策略代码实现(Python…...

在 Conda 环境下配置 Jupyter Notebook 环境和工作目录
作为数据科学家或Python开发者,Jupyter Notebook 是我们日常工作的得力工具。本文将详细介绍如何在 Conda 环境中配置 Jupyter Notebook,包括环境设置和工作目录管理,帮助你打造高效的工作流程。 为什么要在 Conda 环境中使用 Jupyter Noteb…...

MS39531N 是一款正弦驱动的三相无感直流电机驱动器,具有最小振动和高效率的特点
MS39531N 是一款正弦驱动的三相无感直流电机驱动器,具有最小振动和高效率的特点 简述 MS39531 是一款正弦驱动的 三相无感直流电机驱动器 ,具有最小振动和高效率的特点。该驱动器内部集成了基本的闭环速度控制功能,能够根据特定的应用定制电…...

web3-基于贝尔曼福特算法(Bellman-Ford )与 SMT 的 Web3 DeFi 套利策略研究
web3-基于贝尔曼福特算法(Bellman-Ford )与 SMT 的 Web3 DeFi 套利策略研究 如何找到Defi中的交易机会 把defi看做是一个完全开放的金融产品图表,可以看到所有的一切东西;我们要沿着这些金融图表找到一些最优的路径,就…...

分析 java 的 Map<String,Map<String, List<Map<String,Integer>>>>
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;public class Test02 {public static void main(String[] args) {//分析方法:由外层向内层逐渐拆解要定义的变量。再由内向外进行变量赋值//外层第一层&#x…...

ChatterBox - 轻巧快速的语音克隆与文本转语音模型,支持情感控制 支持50系显卡 一键整合包下载
ChatterBox 是一个近期备受关注的开源语音克隆与文本转语音(TTS)模型,由 Resemble AI 推出,具备体积轻巧及超快的推理速度等特色。它也是首个支持情感夸张控制的开放源代码 TTS 模型,这一强大功能能让您的声音脱颖而出…...

前端开发面试题总结-HTML篇
文章目录 HTML面试高频问答一、HTML 的 src 和 href 属性有什么区别?二、什么是 HTML 语义化?三、HTML的 script 标签中 defer 和 async 有什么区别?四、HTML5 相比于 HTML有哪些更新?五、HTML行内元素有哪些? 块级元素有哪些? 空(void)元素有哪些?六、iframe有哪些优点…...

嵌入式学习--江协stm32day4
只能说拖延没有什么好结果,欠下的债总是要还的。 ADC 模拟信号转化为数字信号,例如温度传感器将外部温度的变化(模拟信号),转换为内部电压的变化(数字信号) IN是八路输入,下方是选择…...

【Matlab】连接SQL Server 全过程
文章目录 一、下载与安装1.1 SQL Server1.2 SSMS1.3 OLE DB 驱动程序 二、数据库配置2.1 SSMS2.2 SQL Server里面设置2.3 设置防火墙2.4 设置ODBC数据源 三、matlab 链接测试 一、下载与安装 微软的,所以直接去微软官方下载即可。 1.1 SQL Server 下载最免费的Ex…...
MS8551/MS8552/MS8554 单电源、轨到轨输入输出、高精度运放,可替代AD8551/AD8552/AD8554
MS8551/MS8552/MS8554 单电源、轨到轨输入输出、高精度运放,可替代AD8551/AD8552/AD8554 简述 MS8551/8552/8554 是轨到轨输入输出的高精度运算放大器,它有极低的输入失调电压和偏置电流,单电源电压范围为 1.8V 到 5V 。 MS8551/8552/85…...
什么是 Ansible 主机和组变量
Ansible 是一款强大的自动化工具,可简化配置管理、应用程序部署和预配等 IT 任务。其最有价值的功能之一是能够定义变量,从而为不同的主机和组定制剧本。本文将解释 Ansible 中组变量和主机变量的概念,并通过实际示例说明它们的用法。 Ansib…...
F#语言的区块链
F#语言在区块链中的应用 引言 区块链技术在过去十年中迅速崛起,成为了推动金融、供应链、物联网等多个领域创新的重要力量。近年来,随着区块链技术的普及,各种编程语言也纷纷被应用于区块链的开发中。F#语言作为一种功能性编程语言…...

9.RV1126-OPENCV 视频的膨胀和腐蚀
一.膨胀 1.视频流的膨胀流程 之前膨胀都是在图片中进行的,现在要在视频中进行也简单,大概思路就是:获取VI数据,然后把VI数据给Mat化发给VENC模块,然后VENC模块获取,这样就完成了。流程图: 2.代…...
查找 Vue 项目中未使用的依赖
在 Vue 项目中查找未使用的依赖可以通过以下几种方法: 1. 使用 depcheck 工具 depcheck 是一个专门用于查找项目中未使用依赖的工具。 安装: bash npm install -g depcheck使用: bash depcheck它会列出: 未使用的依赖缺失…...

华为OD机考-内存冷热标记-多条件排序
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextInt();int[] arr new int[a];for(int…...
UDP 与 TCP 调用接口的差异:面试高频问题解析与实战总结
在日常开发中,我们经常使用封装良好的 TCP 协议栈,比如 HTTP 客户端、Moudou 网络库等,因此很少从“裸 API”角度深入了解 TCP 和 UDP 的套接字调用流程。但在一些系统底层开发或者网络编程面试中,常被问到“TCP 和 UDP 的调用流程…...

AI时代:学习永不嫌晚,语言多元共存
最近看到两个关于AI的两个问题,“现在开始学习AI,是不是为时已晚?”、“AI出现以后,翻译几乎已到末路,那么,随着时代的进步,中文会一统全球吗?” 联想到自己正在做的“万能AI盒”小程…...
『React』Fragment的用法及简写形式
在 React 渲染组件时,每个组件只能返回一个根节点(root element)。传统上,如果我们需要渲染多条并列的元素,通常会使用一个多余的 <div> 或者其他容器标签将它们包裹起来。但是,这样会在最终的 HTML …...
强化学习入门:交叉熵方法数学推导
前言 最近想开一个关于强化学习专栏,因为DeepSeek-R1很火,但本人对于LLM连门都没入。因此,只是记录一些类似的读书笔记,内容不深,大多数只是一些概念的东西,数学公式也不会太多,还望读者多多指教…...
CSS3 的特性
目录 CSS3 的特性CSS3 的三大特性1. 层叠性2. 继承性3. 优先级 CSS3 新增特性1. 选择器2. 盒模型3. 背景4. 渐变5. 过渡6. 动画7. 2D/3D 变换8. 弹性布局9. 网格布局10. 媒体查询11. 多列布局12. 文字阴影和盒子阴影 CSS3 的特性 CSS3 的三大特性 1. 层叠性 定义:…...
Vue前端篇——Vue 3的watch深度解析
📌 前言 在 Vue.js 的世界中,“数据驱动”是其核心理念之一。而在这一理念下,watch 扮演着一个非常关键的角色。它允许我们监听响应式数据的变化,并在其发生变化时执行特定的业务逻辑。 本文将通过实际代码示例,深入…...

行为型设计模式之Mediator(中介者)
行为型设计模式之Mediator(中介者) 1)意图 用一个中介对象来封装一系列的对象的交互。中介者使各对象不需要显示的相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 2)结构 其中ÿ…...

三维图形、地理空间、激光点云渲染技术术语解析笔记
三维图形、地理空间、激光点云渲染技术术语解析笔记 code review! 文章目录 三维图形、地理空间、激光点云渲染技术术语解析笔记1. Minecraft风格的方块渲染2. Meshing(网格化)3. Mipmapping(多级纹理映射)4. Marching Cubes&…...

从webrtc到janus简介
1.基础知识 1.1 信令的基础知识 在 WebRTC(Web Real-Time Communication) 中,信令(Signaling) 是实现浏览器之间实时通信的关键机制,负责在通信双方(或多方)之间传递控制信息&…...

JVM 核心概念深度解析
最近正在复习Java八股,所以会将一些热门的八股问题,结合ai与自身理解写成博客便于记忆 一、JVM内存结构/运行时数据区 JVM运行时数据区主要分为以下几个部分: 程序计数器(PC Register) 线程私有,记录当前线程执行的字节码行号唯…...

api将token设置为环境变量
右上角 可以新增或者是修改当前的环境 环境变量增加一个token,云端值和本地值可以不用写 在返回token的接口里设置后执行操作,通常是登录的接口 右侧也有方法提示 //设置环境变量 apt.environment.set("token", response.json.data.token); 在需要传t…...

SIFT算法详细原理与应用
SIFT算法详细原理与应用 1 SIFT算法由来 1.1 什么是 SIFT? SIFT,全称为 Scale-Invariant Feature Transform(尺度不变特征变换),是一种用于图像特征检测和描述的经典算法。它通过提取图像中的局部关键点,…...

AlphaDrive:通过强化学习和推理释放自动驾驶中 VLM 的力量
AlphaDrive: Unleashing the Power of VLMs in Autonomous Driving via Reinforcement Learning and Reasoning 25年3月来自华中科技大学和地平线的论文 OpenAI 的 o1 和 DeepSeek R1 在数学和科学等复杂领域达到甚至超越了人类专家水平,其中强化学习(R…...

【八股消消乐】如何解决SQL线上死锁事故
😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点ÿ…...

如何使用 HTML、CSS 和 JavaScript 随机更改图片颜色
原文:如何使用 HTML、CSS 和 JavaScript 随机更改图片颜色 | w3cschool笔记 (请勿标记为付费!!!!) 在网页开发中,为图片添加动态效果可以显著提升用户体验。今天,我将向…...