Data Structure and Algorithm | Realization of Maximum Subsequence Sum


Maximum subsequence sum

【topic】

给定(可能有负数)整数a(1)、a(2)、……a(n),求 a(1)+a(2)+……+a(j)的最大值。
为方便起见,若所有的整数为负数,则最大子序列和为0.

也就是:在一系列整数中,找出连续的若干个整数,这若干个整数之和 最大。

【Code】

  • Method 1: Exhaustive method
    • Exhaustively all possible, due to nested three-level for loop, running time O (N ^ 3)
    • Algorithm idea: calculate the sum of each sub-sequence, that is, calculate the sum of the i-th to j-th numbers in the sequence (j> = i), and compare
  • C language version: the function prototype is int maxSubSum (int a []);
#include <stdio.h>

int maxSubSum(int a[]){
	int maxSum = 0;
	int sum, i, j, k;
    int len = sizeof(a) / sizeof(int);
	for(i = 0; i < len; i++){
		for(j = i; j < len; j++){
			sum = 0;
			for(k = i; k <= j; k++){
				sum += a[k];//计算 a[i] 到 a[j] 的和 
			}
			if(sum > maxSum){
				maxSum = sum;
			} 
		}
	}
	return maxSum;
}

int main(){
	int a[] = {-2, 11, -4, 13, -5, -2};
	int max = maxSubSum(a);
	printf("%d\n",max);
	return 0;
}
  • C language version: the function prototype is int maxSubSum (int a [], int n);
#include <stdio.h>

int maxSubSum(int a[], int n){
	int maxSum = 0;
	int sum, i, j, k;
	for(i = 0; i < n; i++){
		for(j = i; j < n; j++){
			sum = 0;
			for(k = i; k <= j; k++){
				sum += a[k];//计算 a[i] 到 a[j] 的和 
			}
			if(sum > maxSum){
				maxSum = sum;
			} 
		}
	}
	return maxSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int len = sizeof(a) / sizeof(int);//有负数所以 strlen(a) 不能用 
	int max = maxSubSum(a, len);
	printf("%d\n",max);	
	return 0;
}
  • Method Two:

    • Simplify on the basis of the first one, remove one layer of for loop, running time O (N ^ 2)
    • Algorithm idea: The third for loop of the first algorithm has a lot of unnecessary repetitive calculations, such as: calculating the sum of i to j, but the sum of i to j-1 has been calculated in the previous loop, no need Repeat the calculation, so the for loop can be removed
  • C language version

#include <stdio.h>

int maxSubSum(int a[], int n){
	int maxSum = 0;
	int sum, i, j;
	for(i = 0; i < n; i++){
		sum = 0;
		for(j = i; j < n; j++){
			sum += a[j];
			if(sum > maxSum){
				maxSum = sum;
			} 
		}
	}
	return maxSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int len = sizeof(a) / sizeof(int);//有负数所以 strlen(a) 不能用 
	int max = maxSubSum(a, len);
	printf("%d\n",max);	
	return 0;
}
  • Method 3: Divide and conquer
    • Algorithmic idea: divide the problem into two roughly equal sub-problems, and then solve them recursively. This is the "divided" part. In the "governance" stage, the solutions of the two sub-problems are patched together and some additional work may be done, and finally the solution of the entire problem is obtained.
    • In this problem, if the sequence is divided into two parts from the middle, the largest subsequence sum may appear in three places, either in the left half of the input data, or in the right half, or across the boundary. The first two cases can be solved recursively. The maximum sum of the third case can be obtained by finding the maximum sum of the first half (including the last element of the first half) and the maximum of the second half (including the first element of the second half) The result is a sum, and the two sums are added at this time.
    • Running time O (N log N)
  • C language version
#include <stdio.h>

int maxSubSum(int a[], int left, int right){
	// 判断是否只有一个元素
    if (left == right) {
        if (a[left] > 0) {
            return a[left];
        } else {
            return 0;
        }
    }
    int center = (left + right) / 2;
    int maxLeftSum = maxSubSum(a, left, center);
    int maxRightSum = maxSubSum(a, center + 1, right);
    // 左端处理
    int maxLeftBorderSum = 0;
    int leftBorderSum = 0;
    int i;
    for (i = center; i >= left; i--) {
    	leftBorderSum += a[i];
        if (leftBorderSum > maxLeftBorderSum) {
            maxLeftBorderSum = leftBorderSum;
        }
    }

    // 右端处理
    int maxRightBorderSum = 0;
    int rightBorderSum = 0;
    for (i = center + 1; i <= right; i++) {
        rightBorderSum += a[i];
        if (rightBorderSum > maxRightBorderSum) {
            maxRightBorderSum = rightBorderSum;
        }
    }
    // 返回最大值
    int maxBorderSum = maxLeftBorderSum + maxRightBorderSum;
	return maxBorderSum > maxLeftSum ? maxBorderSum > maxRightSum ? maxBorderSum : maxRightSum
				: maxLeftSum > maxRightSum ? maxLeftSum : maxRightSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int max = maxSubSum(a, 0, sizeof(a) / sizeof(int) - 1);
	printf("%d\n",max);
	return 0;
}
  • Method 4: Optimal starting point, scanning method

    • Algorithm idea: Let a [i] be the starting point of the largest sequence, then if a [i] is negative, then it cannot represent the starting point of the optimal sequence, because any subsequence containing a [i] as the starting point can be It is improved by using a [i + 1] as a starting point.
    • Similarly, any negative subsequence cannot be the prefix of the optimal subsequence.
    • Running time: O (N)
  • C language version

#include <stdio.h>

int maxSubSum(int a[], int n){
	int maxSum = 0;
	int sum = a[0], i;
	/*考虑如果全是负数,那么返回最大的负数,
	如果最后的和为正,那么就使用扫描法*/
	for(i = 1; i < n; i++){
		if(sum < 0){//当前数小于0,换为下一个数
			sum = a[i];
		}else{
			sum += a[i];
		}
		if(sum > maxSum){
			maxSum = sum;
		}
	}
	return maxSum;
}

int main(){
	//int a[] = {-2, 11, -4, 13, -5, -2};
	int a[] = { -2, 4, -3, 5, 7, -1, 8, 1 };
	int len = sizeof(a) / sizeof(int);//有负数所以 strlen(a) 不能用 
	int max = maxSubSum(a, len);
	printf("%d\n",max);	
	return 0;
}
Published 120 original articles · praised 201 · 230,000 views +

Guess you like

Origin blog.csdn.net/wugenqiang/article/details/105467380