最大化所有可能的子阵列的特定总和

时间:2013-03-09 06:27:18

标签: arrays algorithm sub-array

考虑下面这样的数组:

  {1, 5, 3, 5, 4, 1}

当我们选择子阵列时,我们将其减少到子阵列中的最小数字。例如,子阵列{5, 3, 5}变为{3, 3, 3}。现在,子阵列的总和被定义为所得子阵列的总和。例如,{5, 3, 5}总和为3 + 3 + 3 = 9。任务是找到可以从任何子阵列中获得的最大可能总和。对于上面的数组,最大的和是12,由子数组{5, 3, 5, 4}给出。

是否有可能比O(n 2 )及时更好地解决这个问题?

2 个答案:

答案 0 :(得分:3)

假设这些数字都是非负数,这不仅仅是“最大化直方图中的矩形区域”问题吗?现在已经成名......

O(n)解决方案是可能的。这个网站:http://blog.csdn.net/arbuckle/article/details/710988有一堆巧妙的解决方案。

详细说明我的想法(可能不正确)将每个数字视为宽度为1的直方图矩形。

通过“最小化”子阵列[i,j]并加起来,你基本上得到直方图中矩形的区域,从i到j。

之前出现在SO:Maximize the rectangular area under Histogram上,您找到了代码和说明,以及指向官方解决方案页面(http://www.informatik.uni-ulm.de/acm/Locals/2003/html/judge.html)的链接。

答案 1 :(得分:0)

我尝试的以下算法将具有最初用于对数组进行排序的算法的顺序。例如,如果初始数组使用二叉树排序进行排序,则最佳情况下为O(n),平均情况为O(n log n)。

算法要点:

数组已排序。存储排序值和相应的旧索引。从相应的旧索引创建二叉搜索树,用于确定它可以前进和后退多远而不会遇到小于当前值的值,这将导致最大可能的子数组。

我将在问题[1,5,3,5,4,1]中用数组解释方法

                      1  5  3  5  4  1
                  -------------------------
 array indices =>     0  1  2  3  4  5  
                  -------------------------

此数组已排序。以升序存储值及其索引,如下所示

                                   1  1  3  4  5  5
                                 -------------------------
 original array indices =>         0  5  2  4  1  3  
 (referred as old_index)         -------------------------

重要的是要引用价值及其旧指数;像一个关联数组;

很少有条款要明确:

old_index是指元素的对应原始索引(即原始数组中的索引);

例如,对于元素4,old_index为4; current_index是3;

然而,current_index指的是排序数组中元素的索引; current_array_value引用已排序数组中的当前元素值。

pre指的是前身; succ指的是继承人

此外,min和max值可以直接从排序数组的第一个和最后一个元素获得,分别是min_value和max_value;

现在,算法如下,应该对已排序的数组执行。

算法:

从最左边的元素开始。

对于排序数组左侧的每个元素,应用此算法

    if(element == min_value){

    max_sum = element * array_length;

        if(max_sum > current_max)
        current_max = max_sum;

        push current index into the BST;

    }else if(element == max_value){

        //here current index is the index in the sorted array
        max_sum = element * (array_length - current_index);

        if(max_sum > current_max)
        current_max = max_sum;


        push current index into the BST;

    }else {

        //pseudo code steps to determine maximum possible sub array with the current element 

        //pre is inorder predecessor and succ is inorder successor

        get the inorder predecessor and successor from the BST;



        if(pre == NULL){

            max_sum = succ * current_array_value;


            if(max_sum > current_max)
            current_max = max_sum;


        }else if (succ == NULL){

            max_sum = (array_length - pre) - 1) * current_array_value;

            if(max_sum > current_max)
            current_sum = max_sum;

        }else {

        //find the maximum possible sub array streak from the values

        max_sum = [((succ - old_index) - 1) + ((old_index - pre) - 1) + 1] * current_array_value;

            if(max_sum > current_max)
            current_max = max_sum;

        } 

    }

例如,

原始数组是

                      1  5  3  5  4  1
                  -------------------------
 array indices =>     0  1  2  3  4  5  
                  -------------------------

,排序的数组是

                                   1  1  3  4  5  5
                                 -------------------------
 original array indices =>         0  5  2  4  1  3  
 (referred as old_index)         -------------------------

在第一个元素之后

max_sum = 6 [它将减少到1 * 6]

        0

在第二个元素之后

max_sum = 6 [它将减少到1 * 6]

        0
         \
          5

在第三个元素之后:

        0
         \
          5
         /
        2

inorder遍历导致:0 2 5

应用算法,

max_sum = [((succ - old_index) - 1)+((old_index - pre) - 1)+ 1] * current_array_value;

max_sum = [((5-2)-1)+((2-0)-1)+ 1] * 3            = 12

current_max = 12 [最大可能值]


在第四个元素之后

        0
         \
          5
         / 
        2   
         \
          4

inorder遍历结果为:0 2 4 5

应用算法,

max_sum = 8 [由于它小于12而被丢弃]

在第五个元素之后

max_sum = 10 [减少到2 * 5,因为它小于8而被丢弃]

在最后一个元素之后

max_sum = 5 [减少到1 * 5,因为它小于8而被丢弃]

此算法将具有最初用于对数组进行排序的算法的顺序。例如,如果初始数组使用二进制排序进行排序,则最佳情况下为O(n),平均情况为O(n log n)。

空间复杂度为O(3n)[O(n + n + n),n为排序值,另一个n为旧索引,另一个n为构造BST]。但是,我不确定这一点。任何关于算法的反馈都表示赞赏。