- 算法设计与分析
- 家
- 算法基础知识
- DAA - 简介
- DAA - 算法分析
- DAA-分析方法
- 渐近符号和先验分析
- 时间复杂度
- 马斯特定理
- DAA - 空间复杂性
- 分而治之
- DAA-分而治之
- DAA - 最大最小问题
- DAA-归并排序
- DAA-二分查找
- 施特拉森矩阵乘法
- 唐叶算法
- 河内塔
- 贪心算法
- DAA-贪婪法
- 旅行商问题
- Prim 的最小生成树
- 克鲁斯卡尔的最小生成树
- Dijkstra 的最短路径算法
- 地图着色算法
- DAA-分数背包
- DAA - 带截止日期的作业排序
- DAA - 最佳合并模式
- 动态规划
- DAA-动态规划
- 矩阵链乘法
- 弗洛伊德·沃歇尔算法
- DAA - 0-1 背包
- 最长公共子序列
- 旅行商问题| 动态规划
- 随机算法
- 随机算法
- 随机快速排序
- 卡格的最低削减
- 费舍尔-耶茨洗牌
- 近似算法
- 近似算法
- 顶点覆盖问题
- 设置封面问题
- 旅行推销员近似算法
- 排序技巧
- DAA-快速排序
- DAA-冒泡排序
- DAA——插入排序
- DAA-选择排序
- DAA——希尔排序
- DAA-堆排序
- DAA——桶排序
- DAA——计数排序
- DAA - 基数排序
- 搜索技巧
- 搜索技术介绍
- DAA - 线性搜索
- DAA-二分查找
- DAA - 插值搜索
- DAA - 跳转搜索
- DAA - 指数搜索
- DAA - 斐波那契搜索
- DAA - 子列表搜索
- DAA-哈希表
- 图论
- DAA-最短路径
- DAA - 多级图
- 最优成本二叉搜索树
- 堆算法
- DAA-二叉堆
- DAA-插入法
- DAA-Heapify 方法
- DAA-提取方法
- 复杂性理论
- 确定性计算与非确定性计算
- DAA-最大派系
- DAA - 顶点覆盖
- DAA - P 级和 NP 级
- DAA-库克定理
- NP 硬课程和 NP 完全课程
- DAA - 爬山算法
- DAA 有用资源
- DAA - 快速指南
- DAA - 有用的资源
- DAA - 讨论
设计与分析最大最小问题
让我们考虑一个可以通过分而治之技术解决的简单问题。
问题陈述
算法分析中的最大最小问题是寻找数组中的最大值和最小值。
解决方案
要查找给定大小为n的数组Numbers[]中的最大和最小数字,可以使用以下算法。首先我们介绍朴素方法,然后我们将介绍分而治之的方法。
朴素方法
朴素方法是解决任何问题的基本方法。在这种方法中,可以分别找到最大和最小数。要找到最大和最小数字,可以使用以下简单的算法。
Algorithm: Max-Min-Element (numbers[]) max := numbers[1] min := numbers[1] for i = 2 to n do if numbers[i] > max then max := numbers[i] if numbers[i] < min then min := numbers[i] return (max, min)
例子
#include <stdio.h> struct Pair { int max; int min; }; // Function to find maximum and minimum using the naive algorithm struct Pair maxMinNaive(int arr[], int n) { struct Pair result; result.max = arr[0]; result.min = arr[0]; // Loop through the array to find the maximum and minimum values for (int i = 1; i < n; i++) { if (arr[i] > result.max) { result.max = arr[i]; // Update the maximum value if a larger element is found } if (arr[i] < result.min) { result.min = arr[i]; // Update the minimum value if a smaller element is found } } return result; // Return the pair of maximum and minimum values } int main() { int arr[] = {6, 4, 26, 14, 33, 64, 46}; int n = sizeof(arr) / sizeof(arr[0]); struct Pair result = maxMinNaive(arr, n); printf("Maximum element is: %d\n", result.max); printf("Minimum element is: %d\n", result.min); return 0; }
输出
Maximum element is: 64 Minimum element is: 4
#include <iostream> using namespace std; struct Pair { int max; int min; }; // Function to find maximum and minimum using the naive algorithm Pair maxMinNaive(int arr[], int n) { Pair result; result.max = arr[0]; result.min = arr[0]; // Loop through the array to find the maximum and minimum values for (int i = 1; i < n; i++) { if (arr[i] > result.max) { result.max = arr[i]; // Update the maximum value if a larger element is found } if (arr[i] < result.min) { result.min = arr[i]; // Update the minimum value if a smaller element is found } } return result; // Return the pair of maximum and minimum values } int main() { int arr[] = {6, 4, 26, 14, 33, 64, 46}; int n = sizeof(arr) / sizeof(arr[0]); Pair result = maxMinNaive(arr, n); cout << "Maximum element is: " << result.max << endl; cout << "Minimum element is: " << result.min << endl; return 0; }
输出
Maximum element is: 64 Minimum element is: 4
public class MaxMinNaive { static class Pair { int max; int min; } // Function to find maximum and minimum using the naive algorithm static Pair maxMinNaive(int[] arr) { Pair result = new Pair(); result.max = arr[0]; result.min = arr[0]; // Loop through the array to find the maximum and minimum values for (int i = 1; i < arr.length; i++) { if (arr[i] > result.max) { result.max = arr[i]; // Update the maximum value if a larger element is found } if (arr[i] < result.min) { result.min = arr[i]; // Update the minimum value if a smaller element is found } } return result; // Return the pair of maximum and minimum values } public static void main(String[] args) { int[] arr = {6, 4, 26, 14, 33, 64, 46}; Pair result = maxMinNaive(arr); System.out.println("Maximum element is: " + result.max); System.out.println("Minimum element is: " + result.min); } }
输出
Maximum element is: 64 Minimum element is: 4
def max_min_naive(arr): max_val = arr[0] min_val = arr[0] # Loop through the array to find the maximum and minimum values for i in range(1, len(arr)): if arr[i] > max_val: max_val = arr[i] # Update the maximum value if a larger element is found if arr[i] < min_val: min_val = arr[i] # Update the minimum value if a smaller element is found return max_val, min_val # Return the pair of maximum and minimum values arr = [6, 4, 26, 14, 33, 64, 46] max_val, min_val = max_min_naive(arr) print("Maximum element is:", max_val) print("Minimum element is:", min_val)
输出
Maximum element is: 64 Minimum element is: 4
分析
Naive 方法中的比较次数为2n - 2。
使用分而治之的方法可以减少比较的次数。下面是技术。
分而治之的方法
在这种方法中,数组被分为两半。然后使用递归方法找到每一半中的最大和最小数。然后,返回每半部分的两个最大值中的最大值和每半部分中的两个最小值中的最小值。
在此给定问题中,数组中的元素数量为 $y - x + 1$,其中y大于或等于x。
$\mathbf{\mathit{Max - Min(x, y)}}$ 将返回数组 $\mathbf{\mathit{numbers[x...y]}}$ 的最大值和最小值。
Algorithm: Max - Min(x, y) if y – x ≤ 1 then return (max(numbers[x], numbers[y]), min((numbers[x], numbers[y])) else (max1, min1):= maxmin(x, ⌊((x + y)/2)⌋) (max2, min2):= maxmin(⌊((x + y)/2) + 1)⌋,y) return (max(max1, max2), min(min1, min2))
例子
#include <stdio.h> // Structure to store both maximum and minimum elements struct Pair { int max; int min; }; struct Pair maxMinDivideConquer(int arr[], int low, int high) { struct Pair result; struct Pair left; struct Pair right; int mid; // If only one element in the array if (low == high) { result.max = arr[low]; result.min = arr[low]; return result; } // If there are two elements in the array if (high == low + 1) { if (arr[low] < arr[high]) { result.min = arr[low]; result.max = arr[high]; } else { result.min = arr[high]; result.max = arr[low]; } return result; } // If there are more than two elements in the array mid = (low + high) / 2; left = maxMinDivideConquer(arr, low, mid); right = maxMinDivideConquer(arr, mid + 1, high); // Compare and get the maximum of both parts result.max = (left.max > right.max) ? left.max : right.max; // Compare and get the minimum of both parts result.min = (left.min < right.min) ? left.min : right.min; return result; } int main() { int arr[] = {6, 4, 26, 14, 33, 64, 46}; int n = sizeof(arr) / sizeof(arr[0]); struct Pair result = maxMinDivideConquer(arr, 0, n - 1); printf("Maximum element is: %d\n", result.max); printf("Minimum element is: %d\n", result.min); return 0; }
输出
Maximum element is: 64 Minimum element is: 4
#include <iostream> using namespace std; // Structure to store both maximum and minimum elements struct Pair { int max; int min; }; Pair maxMinDivideConquer(int arr[], int low, int high) { Pair result, left, right; int mid; // If only one element in the array if (low == high) { result.max = arr[low]; result.min = arr[low]; return result; } // If there are two elements in the array if (high == low + 1) { if (arr[low] < arr[high]) { result.min = arr[low]; result.max = arr[high]; } else { result.min = arr[high]; result.max = arr[low]; } return result; } // If there are more than two elements in the array mid = (low + high) / 2; left = maxMinDivideConquer(arr, low, mid); right = maxMinDivideConquer(arr, mid + 1, high); // Compare and get the maximum of both parts result.max = (left.max > right.max) ? left.max : right.max; // Compare and get the minimum of both parts result.min = (left.min < right.min) ? left.min : right.min; return result; } int main() { int arr[] = {6, 4, 26, 14, 33, 64, 46}; int n = sizeof(arr) / sizeof(arr[0]); Pair result = maxMinDivideConquer(arr, 0, n - 1); cout << "Maximum element is: " << result.max << endl; cout << "Minimum element is: " << result.min << endl; return 0; }
输出
Maximum element is: 64 Minimum element is: 4
public class MaxMinDivideConquer { // Class to store both maximum and minimum elements static class Pair { int max; int min; } static Pair maxMinDivideConquer(int[] arr, int low, int high) { Pair result = new Pair(); Pair left, right; int mid; // If only one element in the array if (low == high) { result.max = arr[low]; result.min = arr[low]; return result; } // If there are two elements in the array if (high == low + 1) { if (arr[low] < arr[high]) { result.min = arr[low]; result.max = arr[high]; } else { result.min = arr[high]; result.max = arr[low]; } return result; } // If there are more than two elements in the array mid = (low + high) / 2; left = maxMinDivideConquer(arr, low, mid); right = maxMinDivideConquer(arr, mid + 1, high); // Compare and get the maximum of both parts result.max = Math.max(left.max, right.max); // Compare and get the minimum of both parts result.min = Math.min(left.min, right.min); return result; } public static void main(String[] args) { int[] arr = {6, 4, 26, 14, 33, 64, 46}; Pair result = maxMinDivideConquer(arr, 0, arr.length - 1); System.out.println("Maximum element is: " + result.max); System.out.println("Minimum element is: " + result.min); } }
输出
Maximum element is: 64 Minimum element is: 4
def max_min_divide_conquer(arr, low, high): # Structure to store both maximum and minimum elements class Pair: def __init__(self): self.max = 0 self.min = 0 result = Pair() # If only one element in the array if low == high: result.max = arr[low] result.min = arr[low] return result # If there are two elements in the array if high == low + 1: if arr[low] < arr[high]: result.min = arr[low] result.max = arr[high] else: result.min = arr[high] result.max = arr[low] return result # If there are more than two elements in the array mid = (low + high) // 2 left = max_min_divide_conquer(arr, low, mid) right = max_min_divide_conquer(arr, mid + 1, high) # Compare and get the maximum of both parts result.max = max(left.max, right.max) # Compare and get the minimum of both parts result.min = min(left.min, right.min) return result arr = [6, 4, 26, 14, 33, 64, 46] result = max_min_divide_conquer(arr, 0, len(arr) - 1) print("Maximum element is:", result.max) print("Minimum element is:", result.min)
输出
Maximum element is: 64 Minimum element is: 4
分析
令T(n)为 $\mathbf{\mathit{Max - Min(x, y)}}$ 进行的比较次数,其中元素数量 $n = y - x + 1$。
如果T(n)代表数字,那么递推关系可以表示为
$$T(n) = \begin{cases}T\left(\lfloor\frac{n}{2}\rfloor\right)+T\left(\lceil\frac{n}{2}\rceil\right )+2 & 对于\: n>2\\1 & 对于\:n = 2 \\0 & 对于\:n = 1\end{cases}$$
让我们假设n是2的幂的形式。因此,n = 2 k,其中k是递归树的高度。
所以,
$$T(n) = 2.T (\frac{n}{2}) + 2 = 2.\left(\begin{array}{c}2.T(\frac{n}{4}) + 2\end{数组}\right) + 2 ..... = \frac{3n}{2} - 2$$
与 Naïve 方法相比,分治法中的比较次数较少。然而,使用渐近符号,这两种方法都由O(n)表示。