数据结构与算法之分治法

news2025/1/21 10:14:11

文章目录

  • 前言
  • 1.递归解决阶乘函数
  • 2.归并排序算法
    • 2.1 归并排序的概念
    • 2.2 分治法的三步曲
    • 2.3 归并排序的动画
    • 2.4 归并排序算法(C语言代码)
  • 3.最大子序列和问题
    • 3.1 问题的定义
    • 3.2 分治的思路
    • 3.3 简单的分解下代码的结果
    • 3.4 算法代码
    • 3.5 测试结果

前言

分治法首先需要明白递归的概念:

递归: 是指子程序直接调用自己或者通过一系列调用语句间接调用自己,是一种描述问题和解决问题的常用方法。递归的两个基本要素:
1.边界条件:也就是递归终止调用的条件。
2.递归出口:递归表达式,大问题分解为小问题。

分治算法的一般有几个步骤:

  1. 分解 :分析原来的问题,将原问题分解成一系列子问题。
  2. 求解:递归求解各个子问题。若子问题足够小,则直接求解。
  3. 合并:将子问题的解合并成原问题的解。

以下将分析几个典型例子。

1.递归解决阶乘函数

阶乘函数的定义大家都知道。
1)边界条件 n=0,n!=1
2) 递归体 n>0,n!=n*(n-1)

C语言代码:

/**
 1. 阶乘的算法
 2. @param n
 3. @return
 */
int Fac(int n){
    if(n==0)
        return 1;
    else
        return n* Fac(n-1);
}

算法

2.归并排序算法

2.1 归并排序的概念

归并排序是将待排序的元素分成两个大致相同的两个子序列,分别对子序列进行排序,最终将排好序的子序列合并为排序的序列。

2.2 分治法的三步曲

大致分为以下几步:

  1. 分解。将n个元素分成n/2个元素的子序列。
  2. 求解。用归并排序对两个子序列递归排序。
  3. 合并。合并两个排序好的子序列得到排序结果。

2.3 归并排序的动画

归并排序算法

2.4 归并排序算法(C语言代码)

/**
 * 归并排序
 * @param a 待排序的数组
 * @param l 左边的
 * @param r 右端
 */
void MergeSort(int a[],int l, int r){
    //计算分组的中间位置
    int m;
    if (l < r){
        //计算中间的位置
        m = (l+r)/2;
        //递归左边
        MergeSort(a,l,m);
        //递归右边
        MergeSort(a,m+1,r);
        //合并结果
        Merge(a,l,m,r);
    }
}
/**
 * 合并排序的结果
 * @param a
 * @param l
 * @param m
 * @param r
 */
void Merge(int a[], int l, int m, int r) {
    //左边的长度,定义右边的长度
    int lLen=m-l+1 ,rLen=r-m;
    //定义临时数组存放左边的排序结果以及右边的排序结果
    int L[50],R[50];
    //取出左边的元素
    for(int i=0 ; i < lLen ; i++){
       L[i]=a[l+i];
    }
    //取出右边的元素
    for(int j = 0 ; j < rLen; j++){
        R[j]=a[m+j+1];
    }
    //很关键,这个值一定要设置为最大
    L[lLen] = INT_MAX;
    R[rLen] = INT_MAX;
    //开始比较大小
    int i=0,j=0;
    for(int k = l; k < r+1 ; k++){
        if(L[i] < R[j]){
            a[k]=L[i];
            i++;
        }else{
            a[k]=R[j];
            j++;
        }
    }
}

测试代码:
测试

3.最大子序列和问题

3.1 问题的定义

给定n个整型数组组成的蓄力A1,A2,…An,求该序列中子序列的字段和的最大值,当所有序列所有的整型均为负数整数时,其最大字段和为0。
example:
当序号为[-2,6,-4,8,-5,3]时,最大子序列的和为10=6+(-4)+8。

3.2 分治的思路

普通的计算,只有循环遍历所有的子段求和进行比较求解,这样的时间复杂度比较高,这种也就是暴力算法解题的思路,第一遍单个元素作为和比较,得出最大和为8,第二次遍历两个连续元素的组合,第三次遍历三个元素的组合,第四次组合…比较简单,这里不在代码。

  1. 分解。将序列拆分为n个子序列,最大值分为三种情况,所有序列的和分为三种情况。
    (1) 所有序列的的最大字段和在序列的1/2序列左边的和相同。
    (2) 所有序列的的最大字段和在序列的1/2序列右边的和相同。
    (3) 所有序列的的最大字段和在序列的1/2序列左和右边的和相同

  2. 求解。
    递归分段求解1/2字段和。由于序列是连续的,此问题的关键在于求和的时候从1/2向两边扩展求和,这样就能包含前两种情况,第三种情况是从中间1/2处左右两边子序列和的最大值。

  3. 合并。最终的结果就是三个情况的和最大结果。

3.3 简单的分解下代码的结果

以序列[-2,6,-4,8,-5,3]为例。
在这里插入图片描述
此处写比较费劲,看代码输出。

3.4 算法代码

/**
 * 打印数组
 * @param a
 * @param left
 * @param right
 */
void printArr(int *a,int left,int right){
    for (int i = left; i <= right ; ++i) {
        printf("%d,",a[i]);
    }
    printf("\n");
}
/**
 * 求解最大的字段序列和
 * @param a
 * @param left
 * @param right
 * @return
 */
int MaxSubSeqSum(int * a,int left,int right){
    int sum = 0 ;
    int i;
    //遍历到单个元素
    if(left == right){
        if(a[left]>0)  sum=a[left];
        else sum=0;
    }else{
        //循环遍历
        int med=(left+right)/2;
        int leftSum= MaxSubSeqSum(a,left,med);
        int rightSum= MaxSubSeqSum(a,med+1,right);
        //计算左边的序列的字段和
        int subLeftSum=0,s1=0;
        printArr(a,left,med);

        for ( i = med; i >=left ; i--) {
            subLeftSum+=a[i];
            if (subLeftSum > s1) s1=subLeftSum;
        }
        printf("the left sum is %d",subLeftSum);
        printf("\n");
        //计算右边的序列的字段和
        printArr(a,med,right);
        int subRightSum=0,s2=0;
        for (i = med+1; i <= right  ; i++) {
            subRightSum+=a[i];
            if (subRightSum > s2) s2=subRightSum;
        }
        printf("the right sum is %d",subRightSum);
        printf("\n");
        //左右两边之和
        sum=s1+s2;
        if(sum < leftSum) sum=leftSum;
        if(sum < rightSum) sum=rightSum;
    }
    return sum;
}

3.5 测试结果

int main(){
    int a[] = {-2,6,-4,8,-5,3};
    int result= MaxSubSeqSum(a,0,5);
    printf("the final result is :%d",result);
}

代码执行递归过程。

-2,
the left sum is -2 
-2,6,
the right sum is 6 
-2,6,
the left sum is 4  
6,-4,
the right sum is -4
8,
the left sum is 8  
8,-5,
the right sum is -5
8,-5,
the left sum is 3  
-5,3,
the right sum is 3 
-2,6,-4,
the left sum is 0 
-4,8,-5,3,        
the right sum is 6
the final result is :10

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1007324.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu18.04遇到的nodejs的坑记录

Ubuntu18.04安装nodejs的正确姿势 问题回顾 给我的博客网站整上代码高亮插件&#xff0c;在本地运行一切完美&#xff0c;可在我的Ubuntu18.04 bionic版本服务器上运行却报了以下的错误 ERROR in ./node_modules/highlight.js/lib/languages/xml.js Module parse failed: Er…

安装最新版React devtool

1.按照官方文档执行 我这里只想在项目里安装&#xff0c;因此执行的 npm install react-devtools^4 2.安装完成后&#xff0c;在 package.json里加入启动命令 "script": {"dev": "react-devtools" }执行npm run dev会弹出一个窗口 如果是全局…

Redis从简单到高级的总结(超详细)

Redis简单 1、Redis Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件。**官网&#xff1a;**https://redis.io **中文网&#xff1a;**https://www.redis.net.cn/ **key-value结构存储&#xff1a;****主要特点&#xff1a;**- 基…

Vue3 监听属性-watch

文章目录 Vue3 监听属性-watch1. 概念2. 实例2.1 通过使用 watch 实现计数器2.2 千米与米之间的换算2.3 异步加载中使用 watch2.4 小计 Vue3 监听属性-watch 1. 概念 Vue3 监听属性 watch&#xff0c;可以通过 watch 来响应数据的变化。 watch 的作用&#xff1a;用于监测响应…

Navicate操作说明

Navicate介绍 源自百度百科 “Navicat”是一套可创建多个连接的数据库管理工具&#xff0c;用以方便管理 MySQL、Oracle、PostgreSQL、SQLite、SQL Server、MariaDB 和 MongoDB 等不同类型的数据库 操作文档 1.想找出某字段同时满足多个值&#xff0c;比如id值为7或8的记录 方…

pcl--第二节 深度图像RangeImage

从点云创建深度图 目前深度图像的获取方法有激光雷达深度成像法&#xff0c;计算机立体视觉成像&#xff0c;坐标测量机法&#xff0c;莫尔条纹法&#xff0c;结构光法等等&#xff0c;针对深度图像的研究重点主要集中在以下几个方面&#xff0c; 深度图像的分割技术深度图像…

G. The Great Equalizer

Problem - G - Codeforces 思路&#xff1a;通过它给定的这个操作&#xff0c;我们能够发现操作的本质&#xff0c;在排序后&#xff0c;其实每次操作之后&#xff0c;都会把相邻的两个数的差值减少1&#xff0c;所以最大的操作次数就是相邻的最大的差值&#xff0c;并且这个是…

Pytorch学习:torch.max()

文章目录 torch.max()dimkeepdimdim0dim1 out&#xff1a;返回命名元组 (values, indices) torch.max() torch.max(input) → Tensor&#xff1a;返回 input 张量中所有元素的最大值。 注意输入的必须是张量形式&#xff0c;输出的也为张量形式 当输入为tuple类型时&#xf…

如何写营销软文?写营销软文需要注意什么?

营销软文是企业推广产品或服务的重要手段之一。一篇优秀的营销软文能够吸引读者的关注并引起他们的购买欲望&#xff0c;进而增加转化率。本文伯乐网络传媒将分享如何写好营销软文&#xff0c;以及注意事项&#xff0c;帮助您提升营销软文的效果。 一、明确目标受众和营销目标 …

基于SSM的汽车租赁系统

基于SSM的汽车租赁系统【附源码文档】、前后端分离 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatisVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 【主要功能】 角色&#xff1a;管理员、用户 管理员&#xff1a;用户管理、汽车…

【LeetCode题目详解】第十章 单调栈part01 739. 每日温度 ● 496.下一个更大元素 I (day58补)

本文章代码以c为例&#xff01; 一、力扣第739题&#xff1a;每日温度 题目&#xff1a; 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。…

[Google DeepMind] LARGE LANGUAGE MODELS AS OPTIMIZERS

Large Language Models as Optimizers 文章链接 总体架构Optimization by PROmpting (OPRO)&#xff1a;最开始输入meta-prompt&#xff0c;这个初始的meta-prompt基本上只是对优化任务进行了描述(也会有few-shot example)。输入后LLM便会生成一个solution&#xff0c;这个sol…

解决SpringMVC在JSP页面取不到ModelAndView中数据

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 问题描述 ModelAndView携带数据跳转到指定JSP页面后在该页面通过EL表达式取不到原本存放在ModelAndView中的数据。 问题原因 在IDEA中创建Maven工程时web.xml中默认的约束…

贝叶斯网络实战(附代码)

贝叶斯网络实战 1. 建立虚拟环境2. 学生是否获得推荐信3. 泰坦尼克数据集预测存活人员参考 1. 建立虚拟环境 conda create -n BayesNN38 python3.8 conda activate BayesNN38 pip install pgmpy2. 学生是否获得推荐信 代码如下&#xff1a; from pgmpy.models import Bayesia…

Spring Boot集成EasyExcel实现数据导出

在本文中&#xff0c;我们将探讨如何使用Spring Boot集成EasyExcel库来实现数据导出功能。我们将学习如何通过EasyExcel库生成Excel文件&#xff0c;并实现一些高级功能&#xff0c;如支持列下拉和自定义单元格样式&#xff0c;自适应列宽、行高&#xff0c;动态表头 &#xff…

处理:对于移动类型Z21和帐户8051010100 供应商货物移动 (014)的不同的字段选择

对于移动类型Z21和帐户8051010100 供应商货物移动 (014)的不同的字段选择 消息编号 M7093 诊断 来自 移动类型Z21和 总帐科目8051010100的字段选择串的比较显示了在一点或更多点处有不兼容的字段选择组合。 字段选择不同的字段&#xff1a;供应商货物移动 范例 在移动类型屏幕上…

JavaScript逻辑题:输出1000之内的所有完数。所谓完数指的是:如果一个数恰好等于它的所有因子之和,这个数就称为完数。

// 定义函数function judgeNum(){// 定义数组存储完数let arr []// for循环1000以内的所有数for(let i 1;i<1000;i){// 定义sum存储一个数的因子之和let sum 0;// 内层循环一个数的因子for(let j 1;j<i;j){if(i % j 0){sum j;}}// 如果一个数和它的因子之和相等&am…

【idea】将已有项目文件夹添加为项目模块

前后效果 变更方法 适用场景 项目为maven项目适用&#xff0c;如果不是maven项目不适用

IDEA指定Maven settings file文件未生效

背景&#xff1a;在自己电脑上配置的时候&#xff0c;由于公司项目和我自己的项目的Maven仓库不一致&#xff0c;我就在项目中指定了各自的Maven配置文件。但是我发现公司的项目私有仓库地址IDEA总是识别不到&#xff01; 俩个配置文件分别是&#xff1a; /Users/sml/Mine/研发…

Vue3 快速入门和模板语法

vite方式建立项目 1.安装vue vite组件 # 安装组件或更新 npm i vite vue -g# 建立项目 npm init vue v301 cd v301 npm run dev# 建立项目 vue create vue v302 cd v302 npm run dev 2. 配置项目vite.config.ts import {fileURLToPath, URL} from node:urlimport {defineConfi…