maximum-subarray

1.题目描述

  输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。

2.算法分析与实现

  设currSum(i)为前i个元素中,以第i个元素为结尾,和最大的连续子数组的和。那么可得一下递推公式

      currSum(i+1) =  currSum(i) + a(i) (currSum >= 0)

                  a(i)                     (currSum < 0)

    以上公式很好理解,对于currSum(i+1)来说,等于currSum(i)加上 a[i],但如果currSum(i) < 0,加上一个负数的话,一定会比不加小,所以索性不加

  那么求数组a[n]的最大子数组的问题,就转化成在Max (currSum(i)) (1<= i <=size)   

  基于以上的算法思想,总结出以下两实现方法

  1.方法一

    此实现中的借用一个辅助的数组currSum[n],currSum[i]代表以i个元素为结尾的所有子数组中的最大和

    首先遍历数组a[n],得到currSum[n],然后遍历数组currSum[n],找到所有元素中找到最大的那个即可       

 1 // Author : Jincheng
 2 // Date : 170315
 3 // Description : find max sum of subarray by DP method
 4 // Complexity : Time O(n) Space O(n)
 5 
 6 #include <iostream>
 7 using  namespace std;
 8 
 9 template <typename T>
10 void Print(T *a,int size);
11 
12 template <typename T>
13 void MaxSumSubarray(T *a,int size)
14 {
15     T *currSum = new T[size+1]; // 辅助数组
16     currSum[1] = a[1]; 
17     T maxSum ; // 全局的最大值
18     for(int i = 2;i <= size;i++)
19     {
20         if(currSum[i-1] < 0)
21         {
22             currSum[i] = a[i];
23         }
24         else 
25         {
26             currSum[i] += a[i];
27         }
28     }
29     maxSum = [1];
30     for(int i = 2;i<=size;i++)
31     {    
32         if(maxSum < currSum[i])
33         {
34             maxSum = currSum[i];
35         }
36     }
37     cout << "the max sum of subarray is " << maxSum << endl;
38 
39     delete b;
40 }
41 
42 int main()
43 {
44     int a[] = {0,-1,-2,-7,-8,-5};
45     Print(a,5);
46     MaxSumSubarray(a,5);
47 return 0; 48 } 50 51 template <typename T> 52 void Print(T *a,int size) 53 { 54 for(int i=1;i <= size;i++) 55 56 cout << "a[" << i << "] = " << a[i] << endl; 57 }

   2.方法二

    此方法是方法一的优化。

    在方法一中:

      首先需要一个辅助的数组currSum[n]用来保存以第i个元素结尾的最大子数组和

      并且需要对a[n]进行遍历得到currSum[n],然后在对currSum[n]进行遍历得到maxSum

    通过观察发现我们没必要保存所有的currSum(i),在遍历a[n]时,在求currSum(i)时,我们只需要知道currSum(i-1)就可以了

    所以在方法二中 :

      只需要一个变量currSum用来保存上次求得的最大和

      只需要对a[n]进行一次遍历,在遍历时同时更新currSum和maxSum

 1 // Author : Jincheng
 2 // Date : 170315
 3 // Description : find max sum of subarray by DP method
 4 // Complexity : Time O(n) Space O(1)
 5 
 6 #include <iostream>
 7 using  namespace std;
 8 
 9 template <typename T>
10 void Print(T *a,int size);
11 
12 template <typename T>
13 void MaxSumSubarray(T *a,int size)
14 {
15     T currSum = a[1]; // 当前以第n个数为结尾的子数组最大和
16     T maxSum = currSum; // 全局的最大和
17     int begin = 1,end = 1; // 最大子数组的开始和结尾 
18     int temp = 1; 
19     for (int i = 2;i <= size;i++)
20     {
21         if(currSum > 0)
22         {
23             currSum = currSum + a[i];
24         }
25         else 
26         {
27             currSum = a[i];
28             temp = i;
29         }
30         if(currSum >= maxSum)
31         {
32             maxSum = currSum;
33             begin = temp;
34             end = i;
35         }
36     }
37     cout << "Max sum of subarray begin :" << begin << ", end : " << end << ",the sum is " << maxSum << endl;
38 }
39 
40 int main()
41 {
42     int a[] = {0,-1,-2,-7,-8,-5};
43     Print(a,5);
44     MaxSumSubarray(a,5);
45     return 0;
46 }
47 
48 template <typename T>
49 void Print(T *a,int size)
50 {
51     for(int i=1;i <= size;i++)
52         
53         cout << "a[" << i << "] = " << a[i] << endl;
54 }

 来此一位大牛的实现

 1 typedef struct {
 2     unsigned left;
 3     unsigned right;
 4     int sum;
 5 } max_subarray;
 6 
 7 max_subarray find_maximum_subarray(int A[], unsigned low, unsigned high) {
 8     max_subarray suffixes[high - low];
 9 
10     suffixes[0].left = low;
11     suffixes[0].right = low + 1;
12     suffixes[0].sum = A[low];
13 
14     for (int i = low + 1; i < high; i++) {
15         if (suffixes[i - 1].sum < 0) {
16             suffixes[i].left = i;
17             suffixes[i].right = i + 1;
18             suffixes[i].sum = A[i];
19         } else {
20             max_subarray *previous = &suffixes[i - 1];
21             suffixes[i].left = previous->left;
22             suffixes[i].right = i + 1;
23             suffixes[i].sum = previous->sum + A[i];
24         }
25     }
26 
27     max_subarray *max = &suffixes[0];
28 
29     for (int i = low + 1; i < high; i++) {
30         if (max->sum < suffixes[i].sum) {
31             max = &suffixes[i];
32         }
33     }
34 
35     return *max;
36 }

 

posted on 2017-03-17 17:37  咔叽娃  阅读(178)  评论(0)    收藏  举报

导航