找出连续数组子序列最大值的更好解决方案

时间:2014-07-16 11:26:19

标签: arrays algorithm data-structures

假设给定一个整数数组A,我想找到另一个使用A的COUNT数组。

例如,int A [] = {34,10,15,14,30,27,21,32,50}

对于上面的例子,COUNT []应该是:{0,0,1,0,3,0,0,6,8}

这里,COUNT [i]对应于A [i],COUNT [i]表示A的连续先前元素的数量小于A [i]。

例如,A [1] = 10,COUNT [1] = 0,因为A中没有先前的元素小于A [1]。

A [7] = 32,COUNT [7] = 6,因为32大于前6个连续元素(例如10,15,14,30,27,21)。

我们可以为这个问题找到O(n)解决方案吗?

修改

根据@ user1990169&#39的算法, 我在Java中实现它如下,但由于算法不计算堆栈上不存在的那些索引(在早期迭代中已经弹出),它没有给出预期的输出。

public static void main(String[] args) throws Exception {

    Stack<Integer> stack = new Stack<Integer>();

    // int a[] = new int[] { 53, 2, 7, 5, 15, 12, 10, 38, 72 };
    int a[] = new int[] { 34, 10, 15, 14, 30, 27, 21, 32, 50 };

    int N = a.length;

    int[] count = new int[N];

    int tos = 0;
    int poppedElemIdx = 0;
    int popCount = 0;

    boolean counted = false;

    stack.clear();

    for (int i = 0; i < N; i++) {

        popCount = 0;
        counted = false;
        while (!stack.isEmpty()) {

            tos = stack.peek();

            if (a[tos] > a[i]) {

                stack.push(i);
                count[i] = count[poppedElemIdx] + popCount;
                counted = true;
                break;

            }

            poppedElemIdx = stack.pop();
            popCount++;
            // popCount += (count[poppedElemIdx] + 1);

        }

        if (counted) {
            continue;
        }

        stack.push(i);
        count[i] = popCount;

    }

    // Print count array
    for (int i = 0; i < N; i++) {
        System.out.print(count[i] + " ");
    }

}

2 个答案:

答案 0 :(得分:4)

O(N)空间和O(N)时间复杂度算法。

从左到右遍历数组。保持外部堆栈元素。

A[0] = 34, push 34 onto stack. Count[0] = 0.  
A[1] = 10,  
Now keep popping out from stack till either it is empty 
or you encounter a number greater than the current element (10). 
Here 34 is > 10, hence we push 10 onto stack and make Count[1] = 0.  

A[2] = 15.  
So we pop out 10 from the stack, push 15 onto stack,  
and make Count[2] = Count[ last popped out index ] + Number of indices popped out  
                  = 0 + 1 = 1.  
A[3] = 14.
So we push 14 onto stack and make Count[3] = 0.
A[4] = 30.
So we pop out 14 and 15 from the array, push 30 onto the array 
and make Count[4] = Count[ index of 15 ] + Number of indices popped out(2) 
                  = 1 + 2 = 3.

这样做直到你到达阵列的末尾。

由于每个项目只被推入一次并从堆栈中弹出一次,因此时间复杂度为O(2 * N)= O(N)。

编辑:正如所建议的那样,如果将索引存储在堆栈中而不是值,那会更好。

答案 1 :(得分:0)

对原始算法进行少量修改后的工作程序:

public static void main(String[] args) throws Exception {

    Stack<Integer> stack = new Stack<Integer>();

    int a[] = new int[] { 53, 2, 7, 5, 15, 12, 10, 38, 72 };
    // int a[] = new int[] { 34, 10, 15, 14, 30, 27, 21, 32, 50 };

    int N = a.length;

    int[] count = new int[N];

    int tos = 0;
    int poppedElemIdx = 0;
    int popCount = 0;

    boolean counted = false;

    stack.clear();

    for (int i = 0; i < N; i++) {

        popCount = 0;
        counted = false;
        while (!stack.isEmpty()) {

            tos = stack.peek();

            if (a[tos] > a[i]) {

                stack.push(i);
                count[i] = popCount;
                counted = true;
                break;

            }

            poppedElemIdx = stack.pop();
            popCount += (count[poppedElemIdx] + 1);

        }

        if (counted) {
            continue;
        }

        stack.push(i);
        count[i] = popCount;

    }

    // Print count array
    for (int i = 0; i < N; i++) {
        System.out.print(count[i] + " ");
    }

}