最大子序列和及序列起始位置-全负数也适用-O(N)时间复杂度

有一个很经典的题目:给定一个整数组,求连续子序列的最大和,整数为正、负、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;
    
}

猜你喜欢

转载自blog.csdn.net/poetteaes/article/details/80337488