Max double slice sum 的解法

1. 上题目:

Task description

A non-empty zero-indexed array A consisting of N integers is given.

A triplet (X, Y, Z), such that 0 ≤ X < Y < Z < N, is called a double slice.

The sum of double slice (X, Y, Z) is the total of A[X + 1] + A[X + 2] + ... + A[Y − 1] + A[Y + 1] + A[Y + 2] + ... + A[Z − 1].

For example, array A such that:

    A[0] = 3
    A[1] = 2
    A[2] = 6
    A[3] = -1
    A[4] = 4
    A[5] = 5
    A[6] = -1
    A[7] = 2

contains the following example double slices:

  • double slice (0, 3, 6), sum is 2 + 6 + 4 + 5 = 17,
  • double slice (0, 3, 7), sum is 2 + 6 + 4 + 5 − 1 = 16,
  • double slice (3, 4, 5), sum is 0.

The goal is to find the maximal sum of any double slice.

Write a function:

int solution(int A[], int N);

that, given a non-empty zero-indexed array A consisting of N integers, returns the maximal sum of any double slice.

For example, given:

    A[0] = 3
    A[1] = 2
    A[2] = 6
    A[3] = -1
    A[4] = 4
    A[5] = 5
    A[6] = -1
    A[7] = 2

the function should return 17, because no double slice of array A has a sum of greater than 17.

Assume that:

  • N is an integer within the range [3..100,000];
  • each element of array A is an integer within the range [−10,000..10,000].

Complexity:

  • expected worst-case time complexity is O(N);
  • expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).

Elements of input arrays can be modified.

Copyright 2009–2015 by Codility Limited. All Rights Reserved. Unauthorized copying, publication or disclosure prohibited.

大体意思很简单,就是求以X为中心的不包含X的左右两段slice的和的最大值。

2.题目分析

这个题目我乍看之下,觉得是一个很动态的问题,有三个变量,一个是中心点X,一个是左边界Y,一个是右边界Z;有了这三个点才能确定出一个确定的double slice。暴力算法的时间复杂度有O(N3). 但是题目要求O(N)。所以肯定存在一种简便算法来完成这个操作,即通过空间来换时间。

我们冷静的分析一下。

首先,这个最大点,肯定是以中间点X为轴左右两段相加和。对于X来说,这个点的max等于左边的max加上右边的max。即我们只要知道,加到X-1处左边能够加到的最大max,和,从右加到X+1处,右边的max,两者相加就为以X点为轴的max。对于其他左sum与右sum来说,必然小于这个max。

那么我们再以O(N)的时间复杂度遍历所有X点,找出最大的即可~

所以现在的问题就变成,找出每一个点X,左侧的连续max slice sum,以及右侧是max slice sum。

这时,我们惊喜的发现,通过递推的算法,我们又可以通过O(N)的时间复杂度完成这个问题~

1.如果我们确定了i点左侧最大sum,那么i+1点最侧最大的sum就是 max((sum[i]+A[i]),0)

2.通过递推,可以用线性时间复杂度完成 foreMax[] 的构建。

3.同理,可以完成postMax[]的构建。

通过这两个数组在每一个节点上的求和,我们便可找到最大的double slice sum的值哦~

时间复杂度为 O(3*N), 空间复杂度为O(2*N);

3.结果:

 1 // you can write to stdout for debugging purposes, e.g.
 2 // printf("this is a debug message\n");
 3
 4 int solution(int A[], int N) {
 5     // write your code in C99
 6     int foreMax[N];
 7     int postMax[N];
 8     A[0]=0;
 9     A[N-1]=0;
10
11     foreMax[0]=0;
12     // foreMax[1]=0;
13     postMax[N-1]=0;
14     int i;
15     for(i=1;i<N;i++)
16     {
17         if(foreMax[i-1]+A[i-1]>0)
18         {
19             foreMax[i]=foreMax[i-1]+A[i-1];
20         }
21         else
22         {
23             foreMax[i]=0;
24         }
25     }
26
27     for(i=N-2;i>=0;i--)
28     {
29         if((postMax[i+1]+A[i+1])>0)
30         {
31             postMax[i]=postMax[i+1]+A[i+1];
32         }
33         else
34         {
35             postMax[i]=0;
36         }
37     }
38     int max = 0;
39
40     for(i=1;i<N-1;i++)
41     {
42         if(foreMax[i]+postMax[i]>max)
43         {
44             max = foreMax[i]+postMax[i];
45         }
46     }
47     return max;
48 }
时间: 2024-10-29 07:47:43

Max double slice sum 的解法的相关文章

Poj Double Queue 3481 AVL解法

本题应该挺经典的,因为可以使用好多方法过,适合训练多种高级数据结构和算法. 这里使用AVL平衡二叉树的解法,时间还可以,大概300ms吧,内存很省188k,因为这里使用指针,没有浪费内存. 这里使用Geeks上面的AVL的做法,使用递归更新树,而不使用双亲指针,试了下使用双亲指针,真的好麻烦,要维护多一个指针,容易出错很多. 递归操作二叉树是非常优雅的. 而且不需要使用任何STL容器,非常原始,直接的解法,呵呵,可以控制任何一个细节,还是很好的. #include <stdio.h> #inc

询问任意区间的min,max,gcd,lcm,sum,xor,or,and

给我们n个数,然后有m个询问,每个询问为L,R,询问区间[L,R]的最大最小值,最小公约数,最大公约数,和,异或,或,且 这些问题通通可以用RMQ的思想来解决. 以下用xor来作为例子 设dp[i][j]为以i开头的,长度为2^j的区间的所有值得异或 那么dp[i][j] = dp[i][j-1] xor dp[i+(1<<(j-1))][j-1] 这样,运用动态规划的思想,我们可以在nlogn的时间复杂度内算出以任意点开头的,长度为1,2,4,8...2^j 的区间的异或值. 那么询问任意区

HDU 1003 Max Sum

题目: Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the input cont

hdoj 1003 Max Sum 【最大子段和】【贪心】

题意:... 策略:看着像贪心,感觉也是贪心. 很久之前做的,又做了一遍,好题. 代码: #include<stdio.h> #include<string.h> int s[100005]; int main() { int t, i, j, l, st, en, n, v = 1; scanf("%d", &t); while(t --){ scanf("%d", &n); for(i = 1; i <= n; i

HDU 1024 Max Sum Plus Plus【动态规划求最大M子段和详解 】

Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 29942    Accepted Submission(s): 10516 Problem Description Now I think you have got an AC in Ignatius.L's "Max Sum" problem

oracle中的聚合函数count、max、min、sum、avg以及NVL函数的用法

oracle中的聚合函数count.max.min.sum.avg以及NVL函数的用法 分组函数聚合函数对一组行中的某个列执行计算执行计算并返回单一的值.聚合函数忽略空值.聚合函数经常与 SELECT 语句的 GROUP BY 子句一同使用,所以有的时候也把其称之为分组函数.这类函数通常应用于报表统计中,以下展示Oracle常用的聚合函数的应用. 分组函数的介绍 作用于一组数据,并对一组数据返回一个值. 常见的分组函数有: Count 用来计算有效数据的数量 Min 返回一个数字列或计算列的最小

Hive分析窗体函数之SUM,AVG,MIN和MAX

Hive中提供了非常多的分析函数,用于完毕负责的统计分析. 本文先介绍SUM.AVG.MIN.MAX这四个函数. 环境信息: Hive版本号为apache-hive-0.14.0-bin Hadoop版本号为hadoop-2.6.0 Tez版本号为tez-0.7.0 构造数据: P088888888888,2016-02-10,1 P088888888888,2016-02-11,3 P088888888888,2016-02-12,1 P088888888888,2016-02-13,9 P0

杭电1003(Max Sum) 首次dp

点击打开杭电1003 Problem Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this sequence is 6 + (-1) + 5 + 4 = 14. Input The first line of the inp

Max Sum(最大子串和)

Max Sum Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description Given a sequence a[1],a[2],a[3]......a[n], your job is to calculate the max sum of a sub-sequence. For example, given (6,-1,5,4,-7), the max sum in this