【数组】最大子数组问题(要求时间复杂度最佳)
思路:
就是最大子列和呗,时间复杂度最佳那就是O(n),使用贪心算法。
以下是三种方法,时间复杂度递减
1 // preface.cpp : 基本概念 求最大子列和 2 #include "pch.h" 3 #include <iostream> 4 using namespace std; 5 6 /* 方法一:确定子列的首部,逐个累加,时间复杂度 O(n^2)*/ 7 int MaxSubseqSum1(int n, int a[]) { 8 int max = 0; 9 for (int i = 0; i < n; i++) { 10 int temp = 0;//当前子列和 11 for (int j = i; j < n; j++) { 12 temp += a[j]; 13 if (temp > max) 14 max = temp; 15 } 16 } 17 return max; 18 } 19 20 /* 方法二:分治法,递归分成两份,分别求每个分割后最大子列和,时间复杂度为 O(n*logn)*/ 21 22 23 /*返回三者中的最大值*/ 24 int Max3(int A, int B, int C) { 25 return (A > B) ? (A > C ? A : C) : (B > C ? B : C); 26 } 27 28 /*分治*/ 29 int DivideAndConquer(int a[], int left, int right) { 30 /*递归结束条件:子列只有一个数字*/ 31 // 当该数为正数时,最大子列和为其本身 32 // 当该数为负数时,最大子列和为 0 33 if (left == right) { 34 if (a[left] > 0) 35 return a[left]; 36 return 0; 37 } 38 39 /* 分别递归找到左右最大子列和*/ 40 int center = (left + right) / 2; 41 int MaxLeftSum = DivideAndConquer(a, left, center); 42 int MaxRightSum = DivideAndConquer(a, center+1, right); 43 44 /* 再分别找左右跨界最大子列和*/ 45 int MaxLeftBorderSum = 0; 46 int LeftBorderSum = 0; 47 for (int i = center; i >= left; i--) {//从边界出发向左找 48 LeftBorderSum += a[i]; 49 if (MaxLeftBorderSum < LeftBorderSum) 50 MaxLeftBorderSum = LeftBorderSum; 51 } 52 int MaXRightBorderSum = 0; 53 int RightBorderSum = 0; 54 for (int i = center + 1; i <= right; i++) { // 从边界出发向右边找 55 RightBorderSum += a[i]; 56 if (MaXRightBorderSum < RightBorderSum) 57 MaXRightBorderSum = RightBorderSum; 58 } 59 /*最后返回分解的左边最大子列和,右边最大子列和,和跨界最大子列和三者中最大的数*/ 60 return Max3(MaxLeftSum, MaxRightSum, MaXRightBorderSum + MaxLeftBorderSum); 61 } 62 63 int MaxSubseqSum2(int n, int a[]) { 64 return DivideAndConquer(a, 0, n - 1); 65 } 66 /*“贪心法”,即不从整体最优上加以考虑,只做出某种意义上的局部最优解。 67 其实最大子列和与它的首部和尾部都没有关系,我们只关心它当前的大小。 68 当临时和加上当前值为负时,它对之后子列和肯定没有帮助(甚至只会让之后的和更小!) 69 我们抛弃这段临时和将它置0*/ 70 71 /* 方法三:直接累加,如果累加到当前的和为负数,置当前值或0,时间复杂度为 O(n)*/ 72 int MaxSubseqSum3(int n, int a[]) { 73 int max = 0; 74 int tempmax = 0; 75 for (int i = 0; i < n; i++) { 76 tempmax += a[i]; 77 if (tempmax < 0) { 78 tempmax = 0; 79 } 80 else if (max < tempmax) { 81 max = tempmax; 82 } 83 84 } 85 return max; 86 } 87 88 int main() 89 { 90 int n; 91 int a[100000 + 5]; 92 cin >> n; 93 for (int i = 0; i < n; i++) 94 cin >> a[i]; 95 MaxSubseqSum1(n, a); 96 MaxSubseqSum2(n, a); 97 MaxSubseqSum3(n, a); 98 cout<< MaxSubseqSum1(n, a)<<endl; 99 cout << MaxSubseqSum2(n, a)<<endl; 100 cout << MaxSubseqSum3(n, a)<<endl; 101 return 0; 102 }
作者:PennyXia
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。