算法:Solutions for the Maximum Subsequence Sum Problem

本文对比了四种不同算法在解决最大子数组求和问题上的性能表现,包括两种基于遍历的方法、一种分治法及一种线性时间复杂度算法。通过对不同规模数据集的实验,展示了各种算法的实际运行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The maximum subarray problem is the task of finding the contiguous subarray within a one-dimensional array of numbers (containing at least one positive number) which has the largest sum. For example, for the sequence of values −2, 1, −3, 4, −1, 2, 1, −5, 4; the contiguous subarray with the largest sum is 4, −1, 2, 1, with sum 6. --from wiki


下面我们分析四种算法的时间性能,由于运行时间相差较大,我们分成两组进行对比:

环境:ubuntu 12.04

时间单位:ms

时间性能:presume that the input is preread


第一组:输入数据元素个数2000

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*************************************************************************
    > File Name: algorithm1.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: 2012年12月24日 星期一 22时41分56秒
 ************************************************************************/


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<sys/time.h>

int maxsubsum1( const  int a[],  int n)
{
     int thissum, maxsum, i, j, k;

    maxsum =  0;
     for (i =  0; i < n; i++)
    {
         for (j = i; j < n; j++)
        {
            thissum =  0;
             for (k = i; k <= j; k++)
                thissum += a[k];

             if (thissum > maxsum)
                maxsum = thissum;
        }
    }
     return maxsum;
}

int maxsubsum2( const  int a[],  int n)
{
     int thissum, maxsum, i, j;

    maxsum =  0;
     for (i =  0; i < n; i++)
    {
        thissum =  0;
         for (j = i; j < n; j++)
        {
            thissum += a[j];

             if (thissum > maxsum)
                maxsum = thissum;
        }
    }
     return maxsum;
}

long GetTickCount( void)
{
     struct timeval tv;

    gettimeofday(&tv,  NULL);

     return (tv.tv_sec *  1000 + tv.tv_usec /  1000);
}

int main( void)
{
     int i, n =  2000;
     int *ptr = malloc( sizeof( int) * n);
    srand(time( NULL));
     for (i =  0; i < n; i++)
        ptr[i] = rand() %  50 -  25;
     // adopt algorithm  1
     unsigned  int utimecost = GetTickCount();
     int result = maxsubsum1(ptr, n);
    utimecost = GetTickCount() - utimecost;
    printf( "max subsequence sum is %d, time cost %d\n", result, utimecost);

     // adopt algorithm  2
    utimecost = GetTickCount();
    result = maxsubsum2(ptr, n);
    utimecost = GetTickCount() - utimecost;
    printf( "max subsequence sum is %d, time cost %d\n", result, utimecost);

    free(ptr);

     return  0;
}

输出为:

max subsequence sum is 275, time cost 4423
max subsequence sum is 275, time cost 6


第二组:输入数据元素个数 1000000

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*************************************************************************
    > File Name: divide_conquer.c
    > Author: Simba
    > Mail: dameng34@163.com
    > Created Time: 2012年12月24日 星期一 23时24分41秒
 ************************************************************************/


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <sys/time.h>  /* struct timeval, gettimeofday(), struct itimerval, setitimer(), ITIMER_REAL */

int divide_conquer( int arr[],  int start,  int end)
{
     if(start == end)
         return (arr[start] >  0 ? arr[start] :  0);

     int mid = (start + end) /  2;
     int max_left = divide_conquer(arr, start, mid);
     int max_right = divide_conquer(arr, mid +  1, end);
     // mid subsequence

     int max_left_border =  0;
     int tmp_sum =  0;
     int i;

     for(i = mid; i >= start; i--)
    {
        tmp_sum += arr[i];
         if(tmp_sum > max_left_border)
            max_left_border = tmp_sum;
    }

     int max_right_border =  0;
    tmp_sum =  0;
     for(i = mid +  1; i <= end; i++)
    {
        tmp_sum += arr[i];
         if(tmp_sum > max_right_border)
            max_right_border = tmp_sum;
    }

     int max_mid = max_left_border + max_right_border;
     // max subsequence
     int iresult = max_left;
     if(max_right > iresult)
        iresult = max_right;
     if(max_mid > iresult)
        iresult = max_mid;
     return iresult;
}

int maxsubsum3( const  int a[],  int n)
{
     int j, thissum, maxsum;
    thissum = maxsum =  0;
     for (j =  0; j < n; j++)
    {
        thissum += a[j];

         if (thissum > maxsum)
            maxsum = thissum;
         else  if (thissum <  0)
            thissum =  0;
    }

     return maxsum;
}

long GetTickCount( void)
{
     struct timeval tv;

    gettimeofday(&tv,  NULL);

     return (tv.tv_sec *  1000 + tv.tv_usec /  1000);
}

int main( void)
{
     int i, n =  1000000;
     int *ptr = malloc( sizeof( int) * n);
    srand(time( NULL));
     for (i =  0; i < n; i++)
        ptr[i] = rand() %  50 -  25;
     // adopt divide_conquer algorithm
     unsigned  int utimecost = GetTickCount();
     int result = divide_conquer(ptr,  0, n -  1);
    utimecost = GetTickCount() - utimecost;
    printf( "max subsequence sum is %d, time cost %d\n", result, utimecost);
     // adopt algorithm 3
    utimecost = GetTickCount();
    result = maxsubsum3(ptr, n);
    utimecost = GetTickCount() - utimecost;
    printf( "max subsequence sum is %d, time cost %d\n", result, utimecost);

    free(ptr);

     return  0;
}




输出为:

max subsequence sum is 2410, time cost 217
max subsequence sum is 2410, time cost 4


分析:

在《data structure and algorithm analysis in c》中有对这四种算法时间性能的分析,依次下来分别是O(n^3),O(n^2),O(nlogn),O(n),即使我们在第二组输入的元素个数是第一组的500倍,第二组的运行时间都要比第一组的小。下图2-2是作者写书时测试的时间列表,显然现在的机器运行得更快。



### 最大子序列和问题的解决方法 最大子序列和问题是经典的算法问题之一,目标是从给定数组中找到一个连续子序列,使得该子序列中的元素之和达到最大值。以下是基于动态规划的思想实现的一个高效解决方案。 #### 动态规划法 通过维护两个变量 `current_sum` 和 `max_sum` 来记录当前子序列的最大和以及全局范围内的最大和。遍历整个数组一次即可完成计算: ```python def max_subsequence_sum(nums): current_sum = 0 max_sum = float('-inf') # 初始化为负无穷大 for num in nums: current_sum = max(num, current_sum + num) # 更新当前子序列和 max_sum = max(max_sum, current_sum) # 更新全局最大和 return max_sum ``` 上述代码的时间复杂度为 \(O(n)\),其中 \(n\) 是输入列表的长度[^1]。 #### 示例运行 假设我们有如下输入数据: ```python nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4] result = max_subsequence_sum(nums) print(result) # 输出应为6 (子序列为 [4,-1,2,1]) ``` 此方法的核心在于每次迭代都决定是否将当前数加入到现有子序列或者重新开始一个新的子序列。 #### 非连续子序列的情况 如果允许选取非连续的子序列,则可以采用贪心策略来解决问题。对于这个问题的具体实现方式已经在 JavaScript 的例子中有体现。然而,在 Python 中可以通过简单的排序加累加操作快速得到结果: ```python def non_contiguous_max_subsequence_sum(nums): positive_nums = sorted([num for num in nums if num > 0], reverse=True) total = sum(positive_nums) return total if total != 0 else max(nums) # 测试用例 nums = [7, 2, -8, 4, 10, -2] result = non_contiguous_max_subsequence_sum(nums) print(result) # 应输出23 ``` 这里需要注意的是当所有数值均为负数时需单独处理以确保返回最大的单个元素作为结果。 ### 结论 无论是针对连续还是非连续情况下的最大子序列求和问题都可以借助不同的优化手段有效解决。前者依赖于线性的扫描过程而后者则可能涉及更复杂的逻辑判断或额外的数据结构支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值