手把手教你学会分治法

302 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天

本文目的

  1. 理解递归与分治方法的主要思想;
  2. 掌握利用递归与分治方法来解决实际问题。

二、任务

  1. 对任何非零偶数n总可以找到奇数m和正整数k,使得n=m * 2^k,为了求出两个n阶矩阵的乘积,可以把一个mxm阶矩阵分成2^k个子矩阵, 每个子矩阵有2^k 个元素。当需要求2^k x 2^k 的子矩阵的积时,使用Strassen算法。设计一个传统方法与Strassen算法相结合的矩阵相乘算法,对任何偶数n都可以求出两个n阶矩阵的乘积。并分析算法的计算时间复杂性。
  1. 如果在合并排序算法的分割步骤中,将数组a[0:n-1]划分为 |n^(1/2)|个子数组,每个子数组中有O(n^(1/2))个元素,然后递归地对分割后的子数组进行排序,最后将所得到的 |n^(1/2)|个 排好序的子数组合并成所要求的排好序的数组a[0:n-1]。设计一个实现上述策略的合并排序 算法,并分析算法的计算复杂性。
  1. 半数集问题。
问题描述:给定一个自然数由n幵始可以依次产生半数集set(«)中的数如下:

(1) image.png

(2) 在n的左边加上一个自然数,但该自然数不能超过最近添加的数的一半:
(3) 按此规则进行处理,直到不能再添加自然数为止。
例如,set(6)={6, 16, 26, 126,36, 136}。半数集set(6)中有6个元素。注意,该半数集是多重集。
算法设计:对于给定的自然数n,计算半数集set(n)中的元素个数。
  1. 整数因子分解问题。
问题描述:大于1的正整数n可以分解为n=x1,x2...xn。例如,当n=12时,有8种不同的分解式:
12=12 12=3x2x2
12=6x2 12=2x6
12=4x3 12=2x3x2
12=3x4 12=2x2x3
算法设计:对于给定的正整数n,计算n共有多少种不同的分解式。
第一题:
(1)设计思路
将n阶矩阵分块为m×m的矩阵。用传统方法求2个m阶矩阵的乘积需要计算O(m3)次2个2k x 2k矩阵的乘积。用Strassen矩阵乘法计算2个2k x 2k矩阵的乘积需要的计算时间为O((2k)log7)=O(7k),因此算法的计算时间为O(7km3)
对于任意偶数n,总有n=m (2^k),将矩阵分成mm个2^k阶矩阵。举例:6X6矩阵相乘,可分为9个2x2矩阵,大矩阵用传统算法,小矩阵用Strassen。

image.png

第二题:

(1)设计原理:首先将问题分解为 根号n 个子问题。对每个子问题同样分解为 根号n 个子问题。当子问题足够小时便直接解决子问题不在分解,并始合并子问题。映射到本问题则为对a[0,n-1]排序,首先将a[0,n-1]划分为 根号n 数组并对每个子数组进行排序,然后将子数组进行归并操作。对于每个子数组当问题规模仍然很大时,将其划分为 根号n 子数组,并对子数组进行排序,然后将子数组进行归并操作。当子数组问题规模足够小是直接解决此问题。
(2)设计实现:

image.png

image.png

image.png

(3)设计验证:

image.png //时间1复杂度

/*

  • T (n)={

  • O(1) n<=1

  • n(1/2)T(n(1/2)) n>1

  • }

第三题:

(1) 设计原理:记忆化递归搜索
(2) 设计实现

image.png

(3)设计验证

image.png

第四题:
(1) 设计思路:对每个因子递归求解

image.png

(2) 设计实验

image.png