[算法导论]4.1-5最大连续子数组问题

在线性时间内非递归的求数组的最大连续子数组(连续和最大的子数组)。

题目给出思路为数组A[1...j+1]的最大和子数组,有两种情况:a) A[1...j]的最大和子数组; b) 某个A[i...j+1]的最大和子数组,但思考很久没有理解如何用这个思路设计线性时间算法,希望有人能给予指点。

i点是使A[1]+..+A[i]为负的一个值?

目前的思路是,最大子数组一定位于从某个正数开始,全部求和<=0的一段数组中

从其实点i到目标点j,从第一个正数开始截取尽量长的一段数组,从第一个正数起的最大子数组即为当前数组的最大子数组,若数组和为负,则不可能作为更长数组最大子数组的组成部分(因为还不如从零直接取第一个正数),因此清零数组和并从接下来的第一个正数重新截取。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int A[100];
 5 int main(){
 6     int size;
 7     cin>>size;
 8     bool neg_flag=true;//当全为负数时返回最大值。
 9     int neg_max=-1e10;
10     for(int i=0;i<size;i++){//输入并判断是否全为负。
11         cin>>A[i];
12         if(A[i]>=0){
13             neg_flag=false;
14         }
15         if(A[i]>neg_max){
16             neg_max=A[i];
17         }
18     }
19     if(neg_flag==true){
20         cout<<"max is "<<neg_max<<" start from "<<neg_max<<" to "<<neg_max<<endl;
21         return 0;
22     }
23     int max=-1e10;//最大和。
24     int s=-1;//最大子数组起点。
25     int e=-1;//最大子数组终点。
26     int add=0;//扫描子数组和。
27     int i=0;//扫描子数组起点。
28     int j=0;//扫描子数组终点。
29     while(j<size){
30         add+=A[j];
31         if(add>=0){
32             if(add>=max){
33                 max=add;
34                 s=i;
35                 e=j;
36             }
37             ++j;
38         }
39         else{
40             ++j;
41             i=j;
42             if(j<size){
43                 add=0;
44             }
45         }
46     }
47     cout<<"max is "<<max<<" start from "<<A[s]<<" to "<<A[e]<<endl;
48 
49 }

 

http://www.cnblogs.com/bakari/p/4809684.html?ptvd

根据bakari的博文,还有动态规划的方法,这里的思路似乎可以用来解释上面的代码,但是还是不太能理解动态规划法区间法的区别到底是什么

sum[i+1] = Max(sum[i] + A[i+1], A[i+1])

化简之后,其实就是比较sum[i] ?> 0(sum[i] + A[i+1] ?> A[i+1])

 1 /************************************************************************/
 2 /*  动态规划(对应着上面的贪心法看,略有不同)
 3     求A[1...j+1]的最大和子数组,有两种情况:
 4         1)A[1...j]+A[j+1]的最大和子数组
 5         2)A[j+1]
 6     dp递推式:
 7         sum[j+1] = max(sum[j] + A[j+1], A[j+1])
 8 /************************************************************************/
 9 int MaxSubArraySum_dp(int arr[], int len)
10 {
11     if (len <= 0)
12         exit(-1);
13     int nMax = INT_MIN;
14     int sum = 0;
15     
16     for (int i = 0; i < len; i ++) {
17         if (sum >= 0) 
18             sum += arr[i];
19         else
20             sum = arr[i];
21         if (sum > nMax)
22             nMax = sum;
23     }
24     return nMax;
25 }

 

转载于:https://www.cnblogs.com/kanjin5sui/p/6024729.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值