Учитывая массив A, вычислите B s.t B[i] хранит ближайший элемент слева от A[i], который меньше a[i]

дан массив A[1..n], мы хотим вычислить другой массив B[1..n] такое, что B[i] хранит ближайший элемент слева от A[i] меньше, чем A[i]. Время сложности должно быть O(n).

(для i>1, если слева нет таких меньших элементов, то B[i] содержит A[i] и B[1]=A[1].)

пример :

вход : 6,9,12,17,11
выход:6,6, 9, 12, 9

Я думал о реализации стека,
положи A[1] на B[1], затем нажмите на стек.
для заполнения B[i]сравнить A[i] С ЭЛЕМЕНТАМИ стека и поп, пока вы получите меньший элемент.
наконец, нажимаем A[i] в стек.

выше подход правильный, и есть более дешевое решение?

3 ответов


ваш подход к стеку правильный. Это работает, потому что если вы поп-элемент больше, чем A[i], этот элемент никогда не понадобится для любых элементов, следующих за A[i], потому что вы можете просто использовать .

каждый элемент доступен только дважды, так что это O(n).


подход стека неверен. просто посмотрим, что произойдет, если у вас на входе 6, 9, 12, 17, 11, 15. Когда вы будете работать с 15, ваш стек будет забыт о 12 и 17. Но ближайший маленький левый элемент A[5] равен 12.

алгоритм Saeed тоже не прав. Просто попробуй вычислить.

правильный ответ может быть что-то вроде этого

b[1] = a[1];
s[1] = 1;
for (i=2; i<=n; i+=1) { 
  j = i - 1;
  while (j>1){
    if (a[j]<a[i]) {
      b[i] = a[j];
      s[i] = j;
      break;
    } else {
      j = s[j];
    }
  }
  if (j = 1) {
    b[i] = a[j];
    s[i] = j;
  }
}

Я не уверен, но он имеет сложность O (n).


B[1]=A[1]
push(B[1])
for i=2 to n do
{
    while(A[i] > stack_top ANS stack_top!=NULL)
       pop()
    if(stack_top=NULL)
        B[i]=A[i]
    else
        B[i]=stack_top
    push(A[i])
}

Как указал Ивлад, каждый элемент толкается и всплывает atmost один раз, время O(n).

pl исправьте меня, если есть какая-то ошибка, и мне любопытно любое альтернативное решение, которое избегает стека и дешевле.