算法——分治

学习目标:

  • 掌握算法入门知识

学习内容:

  1. 分治的定义
  2. 例题详细步骤讲解(查找最大和次大元素)

1. 分治的定义

对于一个大规模的问题,将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归 地解这些子问题,然后将各子问题的解合并得到原问题的解。

① 分解:将原问题分解为若干个规模较小且与原问题形式相同的子问题。

② 求解子问题:若子问题规模较小容易被解决则直接求解,否则递归地求解各个子问题。

③ 合并:将各个子问题的解合并为原问题的解。

2. 例题详细步骤讲解

查找最大和次大元素:对于给定的含有n元素的无序序列,求这个序列中最大和次大的两个不同的元素。例如:(2, 5, 1, 4, 6, 3),最大元素为6,次大元素为5。
  • 具体分析:

    对于一个无序序列a,假设最初 a[0]为a[low],a[n-1]为a[high],最大元素max1为0,次大元素max2为0,MAX(x,y)用来求两个元素中的最大值,MIN(x,y)用来求两个元素中的最小值:

    (1)当数组a中只有一个 元素:max1=a[low],max2=-INF。

    (2)当数组a中只有两个 元素:max1=MAX(a[low],a[high]),max2=MIN(a[low],a[high])。

    (3)当数组a中有两个以上元素:

    • 划分:按中间位置 mid=(low+high)/2 分为a[low...mid]和a[mid+1...high]左右两个区间。
    • 求出左区间最大元素lmax1和次大元素lmax2,求出右区间最大元素rmax1和次大元素rmax2。
    • 合并:若lmax1>rmax1,则max1=lmax1,max2=MAX(lmax2,rmax1);否则max1=rmax1,max2=MAX(lmax1,rmax2)。
  • 具体过程:

    (2,5,1,4,6,3)

low=0,high=5,high-low>1数组中有两个以上元素,进行划分。mid=(low+high)/2=2,递归求解a[0...2],a[3...5]}
(划分左区间a[0...2])low=0,high=2,high-low>1数组中有两个以上元素,进行划分。mid=(low+high)/2=1,递归求解a[0...1],a[2...2]

  • (划分左区间a[0...1])low=0,high=1,high-low=1数组中有两个元素。max1=5,max2=2
  • (划分右区间a[2...2])low=2,high=2,high-low=0数组中有1个元素。max1=a[low]=1,max2=-INF
  • 进行合并,在(左区间)中得到的分别为lmax1和lmax2,在(右区间)中得到的分别为rmax1和rmax2。得到该部分max1=5,max2=2

(划分右区间a[3...5])low=3,high=5,high-low>1数组中有两个以上元素,进行划分。mid=(low+high)/2=4,递归求解a[3...4],a[5...5]

  • (划分左区间a[3...4])low=3,high=4,high-low=1数组中有两个元素。max1=6,max2=4
  • (划分右区间a[5...5])low=5,high=5,high-low=0数组中有1个元素。max1=a[low]=3,max2=-INF
  • 进行合并,在(左区间)中得到的分别为lmax1和lmax2,在(右区间)中得到的分别为rmax1和rmax2。得到该部分max1=6,max2=4

进行合并,lmax1=5,lmax2=2,rmax1=6,rmax2=4。得出max1=6,max2=5

  • 具体代码:
c 复制代码
#include <stdio.h>
#include <limits.h> // 用于定义INT_MIN

#define INF INT_MIN

void solve(int a[], int low, int high, int *max1, int *max2) {
    if (low == high) {       // 区间只有一个元素
        *max1 = a[low];
        *max2 = -INF;
    } else if (low == high - 1) { // 区间只有两个元素
        *max1 = (a[low] > a[high]) ? a[low] : a[high];
        *max2 = (a[low] < a[high]) ? a[low] : a[high];
    } else {                // 区间有两个以上元素
        int mid = (low + high) / 2;
        int lmax1, lmax2;
        solve(a, low, mid, &lmax1, &lmax2);      // 左区间求lmax1和lmax2
        int rmax1, rmax2;
        solve(a, mid + 1, high, &rmax1, &rmax2); // 右区间求rmax1和rmax2
        
        if (lmax1 > rmax1) {
            *max1 = lmax1;
            *max2 = (lmax2 > rmax1) ? lmax2 : rmax1; // lmax2, rmax1中求次大元素
        } else {
            *max1 = rmax1;
            *max2 = (lmax1 > rmax2) ? lmax1 : rmax2; // lmax1, rmax2中求次大元素
        }
    }
}

int main() {
    int a[] = {2, 5, 1, 4, 6, 3};
    int n = sizeof(a) / sizeof(a[0]);
    int max1, max2;
    
    solve(a, 0, n - 1, &max1, &max2);
    
    printf("最大元素: %d\n", max1);
    printf("次大元素: %d\n", max2);
    
    return 0;
}
相关推荐
_extraordinary_42 分钟前
笔试专题(八)
算法
爱代码的小黄人4 小时前
深入解析系统频率响应:通过MATLAB模拟积分器对信号的稳态响应
开发语言·算法·matlab
是僵尸不是姜丝7 小时前
每日算法:洛谷U535992 J-C 小梦的宝石收集(双指针、二分)
c语言·开发语言·算法
寒页_9 小时前
2025年第十六届蓝桥杯省赛真题解析 Java B组(简单经验分享)
java·数据结构·经验分享·算法·蓝桥杯
smile-yan9 小时前
拓扑排序 —— 2. 力扣刷题207. 课程表
数据结构·算法·图论·拓扑排序
空雲.9 小时前
牛客周赛88
数据结构·c++·算法
深度学习算法与自然语言处理10 小时前
单卡4090微调大模型 DeepSeek-R1-32B
深度学习·算法·大模型·微调·transformer·面试题
Y1nhl10 小时前
基础算法:滑动窗口_python版本
开发语言·python·算法·力扣·滑动窗口
烟锁池塘柳010 小时前
【数学建模】(智能优化算法)鲸鱼优化算法(Whale Optimization Algorithm)详解与应用
算法·数学建模
地平线开发者11 小时前
【征程 6】工具链 VP 示例中 Cmakelists 解读
算法·自动驾驶