有一个很经典的题目:给定一个整数组,求连续子序列的最大和,整数为正、负、0皆有可能。
先考整数不是全负的情况,和最大的连续子序列,必然是以一个非负数开头,因为和加上一个负数,和变小,此外,和为负数的连续子序列,也不可能是目标子序列的开头的一段序列,因为如果目标序列起始的几个数为负,那么总可以通过将开头的这几个数去掉,这样目标序列的和更大。这种思路能得到一个算法复杂度为O(N)、空间复杂度为O(1)的算法。
有一些实现中,利用上述思路实现了算法,但是很多没有考虑数组的数全负的情况,在全负的情况下,最大子序列和会返回0,这样并没有完全实现题目要求。对于全负的情况,只要在遍历的同时,找到数组中最大的数组,这个最大数字就是最大连续子序列和。
先考整数不是全负的情况,和最大的连续子序列,必然是以一个非负数开头,因为和加上一个负数,和变小,此外,和为负数的连续子序列,也不可能是目标子序列的开头的一段序列,因为如果目标序列起始的几个数为负,那么总可以通过将开头的这几个数去掉,这样目标序列的和更大。这种思路能得到一个算法复杂度为O(N)、空间复杂度为O(1)的算法。
有一些实现中,利用上述思路实现了算法,但是很多没有考虑数组的数全负的情况,在全负的情况下,最大子序列和会返回0,这样并没有完全实现题目要求。对于全负的情况,只要在遍历的同时,找到数组中最大的数组,这个最大数字就是最大连续子序列和。
考虑全负情况的实现如下:
/********************** * get maxium sum of the sub sequence * created by poetteaes * date: 2018-04-15 ***********************/ # include <stdio.h> # define MAX_ARR_LEN 100 int getMaxSum(int arr[], int N, int *maxSUm); int main(void) { int N; int Arr[MAX_ARR_LEN]; int i; int ret; int maxSum; /*input*/ printf("Please input an positive integer N which is between 1 and 100.\n"); scanf("%d", &N); if(N <= 0 || N >MAX_ARR_LEN) { printf("Invalid input N[%d]\n", N); return -1; } printf("Please input %d integer numbers.\n", N); for(i=0; i<N; i++) { scanf("%d", &Arr[i]); } /*getmaxsum*/ ret = getMaxSum(Arr, N, &maxSum); if(ret == -1) { printf("getMaxSum() error\n"); } printf("maxSum: [%d]\n", maxSum); return ret; } /********************** * success: return 0 * error: return -1 * output: maxSum ***********************/ int getMaxSum(int arr[], int N, int *maxSUm) { int i; int sum; int maxNum; int result; if(arr==NULL || N<=0 || N>MAX_ARR_LEN || maxSUm==NULL) return -1; sum = 0; result = arr[0]; maxNum = arr[0]; for(i=0; i<N; i++) { sum += arr[i]; if(sum<0) sum = 0; if(sum > result) result = sum; if(arr[i] > maxNum) maxNum = arr[i]; } if(maxNum < 0) /*all numbers are negetive*/ *maxSUm = maxNum; else *maxSUm = result; return 0; }
如果需要知道目标子序列的起始位置,则改进如下,依旧是算法复杂度为O(N)、空间复杂度为O(1)。
/********************** * get maxium sum of the sub sequence * created by poetteaes * date: 2018-04-15 ***********************/ # include <stdio.h> # define MAX_ARR_LEN 100 int getMaxSum(int arr[], int N, int *maxSUm, int *startIdx, int *endIdx); int main(void) { int N; int Arr[MAX_ARR_LEN]; int i; int ret; int maxSum; int startIndex; int endIndex; /*input*/ printf("Please input an positive integer N which is between 1 and 100.\n"); scanf("%d", &N); if(N <= 0 || N >MAX_ARR_LEN) { printf("Invalid input N[%d]\n", N); return -1; } printf("Please input %d integer numbers.\n", N); for(i=0; i<N; i++) { scanf("%d", &Arr[i]); } /*getmaxsum*/ ret = getMaxSum(Arr, N, &maxSum, &startIndex, &endIndex); if(ret == -1) { printf("getMaxSum() error\n"); } printf("startIndex:[%d], endIndex[%d], maxSum:[%d]\n", startIndex , endIndex, maxSum); return ret; } /********************** * success: return 0 * error: return -1 * output: maxSum ***********************/ int getMaxSum(int arr[], int N, int *maxSUm, int *startIdx, int *endIdx) { int i; int sum; int maxNumIdx; int result; int start, end; if(arr==NULL || N<=0 || N>MAX_ARR_LEN || maxSUm==NULL) return -1; sum = 0; result = arr[0]; maxNumIdx = 0; start = 0; end = 0; for(i=0; i<N; i++) { sum += arr[i]; if(sum<0) { sum = 0; start = i + 1; } if(sum > result) { result = sum; end = i; } if(arr[i] > arr[maxNumIdx]) maxNumIdx = i; } if(arr[maxNumIdx] < 0) /*all numbers are negetive*/ { *startIdx = maxNumIdx; *endIdx = maxNumIdx; *maxSUm = arr[maxNumIdx]; } else { *startIdx = start; *endIdx = end; *maxSUm = result; } return 0; }