求数组中的最大值和最小值

简介: 本文介绍了在程序中如何查找数组中的最大值和最小值,重点讲解了两种算法:普通算法和分治算法。普通算法通过遍历数组直接比较元素大小,找出最值;而分治算法则通过递归将数组划分成更小的部分,分别找出各部分的最大值,最终合并结果得到整个数组的最大值。文章以 {3,7,2,1} 为例,详细演示了两种算法的实现过程,并提供了 C、Java 和 Python 的代码示例。

程序中,我们经常使用数组(列表)存储给定的线性序列(例如 {1,2,3,4}),那么如何查找数组(序列)中的最大值或者最小值呢?


查找数组(序列)中最大值或最小值的算法有很多,接下来我们以 {3,7,2,1} 序列为例讲解两种查找最值的算法,一种是普通算法,另一种是借助分治算法解决。

普通算法

普通算法的解决思路是:创建两个变量 max 和 min 分别记录数组中的最大值和最小值,它们的初始值都是数组中的第一个数字。从第 2 个数字开始遍历数组,每遇到一个比 max 大的数字,就将它存储到 max 变量中;每遇到一个比 min 小的数字,就将它存储到 min 变量中。直到遍历完整个数组,max 记录的就是数组中的最大值,min 记录的就是数组中的最小值。


下面的动画,演示了找最大值的过程:


图1:数组中找最大值的过程

找最小值的过程和图 1 类似,这里不再给出具体的动画演示。

如下是普通算法对应的伪代码:

输入 num[1...n]              // 输入 n 个数字

max <- num[1]                // 将第 1 个数字赋值给 max(表示最大值)

min <- num[1]                // 将第 1 个数字赋值给 min(表示最小值)

for i <- 2 to n:             // 从第 2 个数字开始遍历

   if num[i] > max:         // 如果 max 小于遍历到的数字,则更新 max 的值

       max <- num[i]

   if num[i] < min:         // 如果 min 小于遍历到的数字,则更新 min 的值

       min <- num[i]

Print max , min              // 输出 max 和 min 的值

实现过程非常简单,感兴趣的读者可以自行编写对应的 C、Java 或者 Python 代码。

分治算法

下图展示了用分治算法查找 {3, 7, 2, 1} 中最大值的实现过程:


图2:分治算法找最大值


分治算法的实现思路是:不断地等分数组中的元素,直至各个分组中元素的个数 ≤2。由于每个分组内的元素最多有 2 个,很容易就可以找出其中的最值(最大值或最小值),然后这些最值再进行两两比较,最终找到的最值就是整个数组中的最值。


如图 2 所示,借助“分而治之”的思想,我们将“找 {3, 7, 2, 1} 中最值”的问题转换成了:先找出 {3 , 7]、[2 , 1} 中各自的最值,找出的最值再进行两两比较,最终就可以找到整个数组中的最值。


如下是分治算法求数组中最大值的伪代码:

输入 arr[1...n]           // 输入 n 个数字

arr_max(x , y) :          // 设计一个递归函数,[x , y] 用来限定查找最大数的范围

   if y-x ≤ 1 :         // 如果 y-x 的值小于等于 1,则比较 arr[x] 和 arr[y] 的值,大的就是最大值

       return max(arr[x] , arr[y])

   else :

       // 将 [x , y] 区域划分为 [x , ⌊(x+y)/2⌋ ] 和 [ ⌊(x+y)/2+1⌋ , y] 两个区域,求出两个区域内各自的最大值

       max1 = arr_max(x , ⌊(x+y)/2⌋ )    

       max2 = arr_max( ⌊(x+y)/2+1⌋ , y)

   return max(max1 , max2)   // 比较两个区域的最大值,最终找出 [x , y] 中的最大值


分治算法实现“求数组中最大值”的C语言程序如下:

  1. #include <stdio.h>
  2. //自定义函数,其中 [left,right] 表示 arr 数组中查找最大值的范围
  3. int get_max(int* arr, int left, int right) {
  4. int max_left = 0, max_right = 0, middle = 0;
  5. //如果数组不存在
  6. if (arr == NULL) {
  7. return  -1;
  8. }
  9. //如果查找范围中仅有一个数字
  10. if (right - left == 0) {
  11. return arr[left];
  12. }
  13. //如果查找范围中有 2 个数字,直接比较即可
  14. if (right - left <= 1) {
  15. if (arr[left] >= arr[right]) {
  16. return arr[left];
  17. }
  18. return  arr[right];
  19. }
  20. //等量划分成 2 个区域
  21.    middle = (right - left) / 2 + left;
  22. //得到左侧区域中的最大值
  23.    max_left = get_max(arr, left, middle);
  24. //得到右侧区域中的最大值
  25.    max_right = get_max(arr, middle + 1, right);
  26. //比较左、右两侧的最大值,找到 [left,right] 整个区域的最大值
  27. if (max_left >= max_right) {
  28. return  max_left;
  29. }
  30. else {
  31. return max_right;
  32. }
  33. }
  34. int main() {
  35. int arr[4] = { 3,7,2,1 };
  36. int max = get_max(arr, 0, 3);
  37. printf("最大值:%d", max);
  38. return 0;
  39. }


分治算法实现“求数组中最大值”的 Java 程序如下:

  1. public class Demo {
  2. public static int get_max(int [] arr,int left,int right) {
  3. //如果数组不存在或者数组内没有元素
  4. if (arr == null || arr.length == 0) {
  5. return -1;
  6. }
  7. //如果查找范围中仅有 2 个数字,则直接比较即可
  8. if(right - left <=1) {
  9. if(arr[left] >= arr[right]) {
  10. return arr[left];
  11. }
  12. return arr[right];
  13. }
  14. //等量划分成 2 个区域
  15. int middle = (right-left)/2 + left;
  16. int max_left = get_max(arr,left,middle);
  17. int max_right = get_max(arr,middle+1,right);
  18. if(max_left >= max_right) {
  19. return max_left;
  20. }else {
  21. return max_right;
  22. }
  23. }
  24. public static void main(String[] args) {
  25. int [] arr = new int[] { 3,7,2,1 };
  26. int max = get_max(arr,0,3);
  27.        System.out.println("最大值:"+max);
  28. }
  29. }


分治算法实现“求数组中最大值”的 Python 程序如下:

  1. def get_max(arr,left,right):
  2. #列表中没有数据
  3. if len(arr) == 0:
  4. return -1
  5. #如果查找范围中仅有 2 个数字,则直接比较即可
  6. if right - left <= 1:
  7. if arr[left] >= arr[right]:
  8. return arr[left]
  9. return arr[right]
  10. #等量划分成 2 个区域
  11.    middle = int((right-left)/2 + left)
  12.    max_left = get_max(arr,left,middle)
  13.    max_right = get_max(arr,middle+1,right)
  14. if max_left >= max_right:
  15. return max_left
  16. else:
  17. return max_right
  18. arr = [3,7,2,1]
  19. max = get_max(arr,0,3)
  20. print("最大值:",max,sep='')


以上程序的输出结果均为:

最大值:7

您可以根据伪代码和给出的找数组中最大值的程序,自行编写出找数组中最小值的程序,这里不再过多赘述。

相关文章
|
3月前
|
设计模式 Linux 开发工具
Docker部署会吗?
本段内容主要介绍了Docker常用命令、Linux基础指令及日志查看方法,还涉及SpringMVC的执行流程、设计模式与注解,适合用于面试中技术能力的展示。
118 0
|
3月前
|
存储 搜索推荐 算法
归并排序算法
归并排序是一种基于分治思想的高效排序算法,通过将序列不断划分为不可再分的子序列,再两两合并完成排序。其时间复杂度为O(nlogn),适用于对序列进行升序或降序排列。
211 0
|
3月前
|
算法 Java C语言
弗洛伊德算法求最短路径
弗洛伊德算法用于寻找加权图中各顶点间的最短路径,适用于无向图和有向图。算法基于动态规划思想,通过枚举中间顶点来更新路径,确保最终得到最短路径。该算法要求路径权值非负,否则可能出错。
307 0
|
3月前
|
算法
回溯算法的基本思想
本节介绍回溯算法,通过图1中从A到K的路径查找示例,说明其与穷举法的异同。回溯算法通过“回退”机制高效试探各种路径,适用于决策、优化和枚举问题。
81 0
|
3月前
|
存储 算法
最小生成树的概念与思想
数据结构中的图存储结构包含顶点和边,分为连通图与非连通图。生成树是包含所有顶点、任意两点间仅有一条通路的极小连通图。最小生成树则是权值总和最小的生成树,常用于解决道路建设等实际问题,常用算法有普里姆算法和克鲁斯卡尔算法。
70 0
|
3月前
|
算法 Java C语言
汉诺塔问题
汉诺塔问题源自印度古老传说,涉及将一组圆盘从一根柱子移动到另一根,遵循特定规则。文章详细介绍了该问题的背景、解决思路以及如何使用分治算法实现,同时提供了C语言、Java和Python的代码示例。
194 0
|
3月前
|
算法 搜索推荐
分治算法的基本思想
分治算法通过将复杂问题拆分成多个独立的小问题,逐一解决后再合并结果。适合处理大规模数据,常见应用包括排序、查找最大值/最小值及汉诺塔等问题。
92 0
|
3月前
|
存储 算法 Java
组合问题
组合问题是从给定的N个数中找出任意K个数的所有组合。由于组合内元素无顺序,因此[1,2]和[2,1]视为同一组合。解决组合问题常用的方法包括嵌套循环和回溯算法。嵌套循环适用于K值较小的情况,而回溯算法更适合K值较大的情况,能有效避免多层循环带来的代码复杂性和低效率问题。回溯算法通过递归实现,能动态选择元素并逐步构建组合,最终输出所有符合条件的组合结果。
111 0
|
3月前
|
存储 算法 Java
寻找图中是否存在路径
本节介绍了如何使用并查集判断图中两个顶点之间是否存在有效路径。通过将图的边信息存储到并查集中,同一连通区域的顶点会处于同一集合。只需比较两个顶点的根节点是否相同,即可判断它们是否连通。文中提供了C语言、Java和Python的实现代码,并通过示例验证了算法的正确性。
71 0