# mooc大学浙大数据结构——最大子列和问题

1 篇文章 0 订阅

## 题目一：最大子列和问题

1、如何寻找代码中的可改进点
2、通过改进代码，得到更有效的算法
3、了解在线处理和分而治之思想
4、在线处理类似于动态规划思想

1. 在线处理------O(n)
“在线”的意思是指每输入一个数据就进行即时处理，在任何一个地方中止输入，算法都能正确给出当前的解。
浙江大学陈越老师课件中的方法，用到了动态规划，很像数学中的递推。 我们用 d p i \mathrm{dp}_i 表示以第i个数结尾的最大连续子序列的和，于是存在以下递推公式：
d p i = m a x ( 0 , d p i − 1 ) + n u m i \mathrm{dp}_i = \mathrm{max}(0, \mathrm{dp}_{i-1}) + \mathrm{num}_{i}
【代码1】
int MaxSubseqSum1( int A[], int N) {
int ThisSum, MaxSum;
int i;
ThisSum = MaxSum = 0;
for(int i = 0; i < N; i++) {
ThisSum += A[i]; /* 向右累加 */
if( ThisSum > MaxSum ){
MaxSum = ThisSum; /* 发现更大和则更新当前结果 */
} else if ( ThisSum < 0) { // 如果当前子列和为负
ThisSum = 0; // 则不可能使后面的部分和增大,抛弃之
}
}
return MaxSum;
}


【代码2】递推式的实现

int MaxSubseqSum3(int A[], int N) {
int ThisSum, MaxSum, i;
ThisSum = A[0];
MaxSum = (ThisSum > 0) ? ThisSum : 0;
for (i = 1; i < N; i++) {
if (ThisSum > 0)
ThisSum += A[i];
else
ThisSum = A[i];   //实现递推式dp[n] = max(0, dp[n-1]) + num[n]
if (ThisSum > MaxSum)
MaxSum = ThisSum; /* 发现更大和则更新当前结果 */
}
return MaxSum;
}


【代码3】

int MaxSubseqSum5(int A[], int N) {
int ThisSum, MaxSum, i,lmin;
ThisSum = MaxSum = lmin = 0;
for (i = 0; i < N; i++) {
ThisSum += A[i];
if (ThisSum < lmin)
lmin = ThisSum;
if ((ThisSum - lmin) > MaxSum)
MaxSum = ThisSum - lmin;
}
return MaxSum;
}


————————————————

## 题目二：复杂度2 Maximum Subsequence Sum

Given a sequence of K integers ${N_1​, N_2, …, N_K }$. A continuous subsequence is defined to be { N i , N i + 1 , . . . , N j } \{ N_i, N_{i+1},..., N_j \} where 1 ≤ i ≤ j ≤ K 1≤i≤j≤K . The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:
Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K ( ≤ 10000 ) K (≤10000) . The second line contains K K numbers, separated by a space.

Output Specification:
For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i i and j j (as shown by the sample case). If all the K K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:
10
-10 1 2 3 4 -5 -23 3 7 -21

Sample Output:
10 1 4

1、有正负，负数开头结尾，有并列最大和
2、最大和序列中有负数
3、并列和对应相同i但是不同j，即尾是0，或者开头有0
4、1个正数
5、负数和0
6、全是负数
7、最大和前面有一段是0
8、最大N

【改进代码1】

void MaxSubseqSum(int arr[], int K) {
int this_sum, max_sum, first_num, last_num, first_num_temp;
max_sum = -1;                        // 考虑只增不减，因此赋初值为-1
this_sum = 0;
first_num = first_num_temp = arr[0]; // 全为负数时要求为第一个元素
last_num = arr[K-1];                 // 全为负数时要求为最后一个元素
for (int i = 0; i < K; i++) {
this_sum += arr[i];
if(this_sum > max_sum) {
max_sum = this_sum;
last_num = arr[i];
first_num = first_num_temp;   // 当前和增加到大于max_sum时更新，走到该分支时的first_num_temp是第一个让this_sum>=0的数
} else if ( this_sum < 0) {
this_sum = 0;
first_num_temp = arr[i+1];    // 当前和为负值时，指向下一个数
}
}
if(max_sum == -1) max_sum = 0;        // 全为负数时赋值为0
return;
}


【改进代码2】

void MaxSubseqSum(int arr[], int K) {
int this_sum, max_sum, first_num, last_num, last_num_temp;
max_sum = std::max(arr[K-1], 0);
this_sum = arr[K-1];
last_num = last_num_temp = arr[K-1];
first_num = arr[0];
for (int i = K-2; i >= 0; i--){
if ( this_sum > 0 ) {
this_sum +=arr[i];
} else {
this_sum = arr[i];// dp[i] = max(dp[i-1], 0) + arr[i]
if(arr[i] >= 0)
last_num_temp = arr[i];
}
if ( max_sum <= this_sum ) {
max_sum = this_sum;
first_num = arr[i];
last_num = last_num_temp;
}
}
return;
}


【改进代码3】

void MaxSubseqSum(int arr[], int K) {
int first_num, first_num_temp, last_num;
int this_sum, max_sum, min_sum;
// max_sum = this_sum - min_sum;
this_sum = min_sum = 0;
max_sum = -1;
first_num = first_num_temp = arr[0];
last_num = arr[K-1];
for (int i = 0; i < K; i++) {
this_sum += arr[i];
if(this_sum - min_sum > max_sum) {
max_sum = this_sum - min_sum;
first_num = first_num_temp;
last_num = arr[i];
}
if(this_sum < min_sum) {
min_sum = this_sum;
first_num_temp = arr[i+1];
}
}
if(max_sum == -1) max_sum = 0;
return;
}


• 0
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

03-24
05-05 979

08-17 132
10-13 7592
08-25 323
12-06 1434
05-30 1173
04-01 71
03-08 269
04-18 59