涉及分区和选择的算法

时间:2015-10-17 18:16:40

标签: algorithm

enter image description here

据我所知,利用选择和分区可以最有效地解决这个问题,两者都可以在线性时间内完成。我的想法是选择数组O(n)中的第n个最小元素,在给出的示例中将为34,因此在这种情况下为j = 3。然后是from i = 1 to j - 1,如果序列正在减少,则设置B[i] = j,在序列增加的那一刻,设置B[i] = i + 1并停止。递归调用数组A[j ... n]上的过程。我认为这根本不高效,也不确定它是否正确或算法的最终复杂性是什么。

摘要

(1)使用确定性选择算法o(n)

选择第n个最小值(索引j)

(2)

function:
    for i = 1 to n do
      for j = i + 1 to n do
         if A[j] > A[i] then B[i] = j , B[j] = n + 1
         for k = i + 1 to j - 1 do
            if A[k] < A[k + 1]
               B[k] = j
            else
               B[k] = k + 1
               recursive function(A[j + 1, ... n]) // recursively perform procedure on portion of array starting from j + 1 (after max) to n.

2 个答案:

答案 0 :(得分:3)

这个问题有一个基于堆栈的标准解决方案,即O(n)。 http://www.geeksforgeeks.org/next-greater-element/有一个很好的解释。

以下是该算法的Python实现示例:

def next_greater_element(A):
    """Return an array of 1-based indices to the next strictly greater element, n+1 if none exists"""
    i=0
    n = len(A)
    NGE=[n+1]*len(A)
    stack=[]
    while i<len(A)-1:
        stack.append(i)
        while stack and A[stack[-1]]<A[i+1]:
            x=stack.pop()
            NGE[x]=i+2
        i+=1
    return NGE

A = [8,3,34,13,1,2,21,5]
B = next_greater_element(A)
print B

打印

[3, 3, 9, 7, 6, 7, 9, 9]

重点是每个元素被压入堆栈一次,并且可以从堆栈中弹出一次,因此内部while循环最多可以执行n次。

答案 1 :(得分:1)

只是为了好玩,这里是C语言中基于堆栈的解决方案,结果非常简洁:

#include <stdio.h>

void find_next_largest(int *a, int *b, int n) {
  int s[n], p = -1;
  for (int i = 0; i < n; i++) {
    while (p >= 0 && a[i] > a[s[p]]) b[s[p--]] = i;
    s[++p] = i;
  }
  while (p >= 0) b[s[p--]] = n;
}

int main(void) {
  int a[] = { 8, 3, 34, 13, 1, 2, 21, 5, }, b[100];
  int n = sizeof a / sizeof a[0];
  find_next_largest(a, b, n);
  for (int i = 0; i < n; i++) printf("%d ", b[i] + 1);
  printf("\n");
  return 0;
}

算法的关键思想是每个新的&#34; next&#34; a的元素要么添加到非增加的尾部(它小于或等于最后一个元素),要么正在增加。在后一种情况下,我们想要向后通过非增加尾部,记录新元素是它的下一个最大元素,当找到相等或更大的元素时停止,然后推送新元素。堆栈是用于向后搜索先前遇到的数据的完美数据结构。数组s是堆栈。它将索引存储到等待其下一个最大元素的a个元素中。

请注意,如果新的a元素不大于前一个,则条件&#34;在找到相等或更大的元素时停止弹出,然后按下新元素&#34;当新元素不大于前一个时,自然会做正确的事情。它会弹出零元素并推送新元素。

另请注意,a引用的s元素始终从头部开始按升序排序,这是不变的。