2015-05-17 3 views
7

Otrzymałem tablicę (z n elementów) i muszę znaleźć najmniejszy element po prawej stronie każdego elementu, który jest większy od niego (bieżący element).Największy element obecny po prawej stronie każdego elementu w tablicy

For example : 
    Array =  {8,20,9,6,15,31} 
Output Array = {9,31,15,15,31,-1} 

Czy można to rozwiązać w O(n).? Pomyślałem o przejściu tablicy od prawej strony (zaczynając od n-2) i budowaniu drzewa binarnego wyszukiwania balansu dla pozostałych elementów, ponieważ wyszukiwanie w nim elementu, który jest natychmiast większy niż bieżący element, byłoby O (logn).

Stąd czas złożoność wyjdzie być O (n * (log (n)).

Czy istnieje lepsze podejście do tego problemu?

Odpowiedz

6

Problem przedstawić da się rozwiązać w O(n) czas, ponieważ można zmniejszyć sortowania do niego, a tym samym osiągnąć sortowania O(n) czasie. Say istnieje algorytm, który rozwiązuje ten problem w O(n). Niech będzie element .

Algorytm może być również używany do wyszukiwania elementu najmniejsza do lewo OF i większy niż (o odwracania macierzy przed wykonaniem algorytmu). mogą być również wykorzystywane w celu znalezienia elementu największym do prawo (lub lewej) i mniejszej niż (przez negując elementy przed uruchomieniem algorytmu).

Po czterokrotnym uruchomieniu algorytmu (w czasie liniowym), wiesz, które elementy powinny być po prawej i po lewej stronie każdego elementu. Aby zbudować posortowaną tablicę w czasie liniowym, trzeba zachować indeksy elementów zamiast wartości. Najpierw znajdź najmniejszy element, podążając za "większymi wskaźnikami" w czasie liniowym, a następnie wykonaj kolejne przejście w innym kierunku, aby faktycznie zbudować tablicę.

+0

To nie jest równoznaczne z sortowaniem, znalezienie lokalizacji dowolnego elementu 'a' jest tym, co robisz w quicksort w każdym kroku, i odbywa się tam w O (n). A może źle zrozumiałem twoją redukcję z sortowania? – amit

+0

Wygląda dobrze dla mnie, przynajmniej do sortowania różnych liczb (co jestem prawie pewien, że wystarczy - nie wiem). @amit: po uruchomieniu algorytmu 'v' i' reverse (v) ', dla każdego elementu znasz indeks elementu, który powinien pojawić się po jego prawej stronie (jest to albo następny najmniejszy element po prawej, albo następny najmniejszy element po lewej stronie). Z każdego elementu początkowego można zbudować część rozwiązania o indeksie> = i w czasie O (1) na element. Przerzucenie znaku i jego powtórzenie spowoduje wyświetlenie części po lewej stronie (tj. O indeksie <= i). –

+0

Rozumiem, że otrzymujesz * pojedyncze * położenie elementu, co jest możliwe do wykonania w O (n). dzięki za wytłumaczenie. – amit

2

Nie można tego zrobić w O(n), ponieważ możemy zredukować Element Distinctness Problem (który jest znany w systemie Omega (nlogn), gdy bazuje na porównaniach).

Najpierw zrobić małemu rozszerzeniu do problemu, który nie ma wpływu na jej twardość:

I mieć szereg (n elementów) i trzeba znaleźć najmniejszy element na prawa strona każdego elementu, która jest większa/równa się niż sama (element bieżący).

Dodatek jest pozwolimy element będzie równy do niej (i prawo), a nie tylko ściśle większa niż .

Teraz, biorąc pod uwagę wystąpienie elementu odrębności arr uruchom algorytm dla tego problemu, i patrzeć, czy istnieje jakikolwiek element i takie, że arr[i] == res[i], jeśli nie ma odpowiedzi „cały odrębny”, inaczej: „Nie wszyscy odrębne ".

Jednakże, ponieważ element Distinctness jest oparty na porównywaniu z wartościami Omega(nlogn), powoduje to również taki problem.


(1) Możliwym uzasadnienie dlaczego dodanie równość nie robi problem trudniejsze jest - elementy zakładając są liczbami całkowitymi, możemy po prostu dodać i/(n+1) do każdego elementu w tablicy, teraz na każde dwa elementy, jeśli arr[i] < arr[j] , a także arr[i] + i/(n+1) < arr[j] + j/(n+1), ale jeśli arr[i] = arr[j], to jeśli i<jarr[i] + i/(n+1) < arr[j] + j/(n+1), i możemy mieć ten sam algorytm rozwiązać problem równości.

3

Inni udowodnili, że w ogóle nie jest możliwe rozwiązanie w O (n).

Możliwe jest jednak wykonanie w O (m), gdzie m jest wielkością największego elementu.

Oznacza to, że w niektórych przypadkach (np. Jeśli tablica wejściowa jest znana jako permutacja liczb całkowitych od 1 do n), można to zrobić w O (n).

Poniższy kod przedstawia podejście oparte na standardowej metodzie obliczania następnego większego elementu. (Nie jest to dobre wyjaśnienie tej metody on geeks for geeks)

def next_greater_element(A): 
    """Return an array of indices to the next strictly greater element, -1 if none exists""" 
    i=0 
    NGE=[-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+1 
     i+=1 
    return NGE 

def smallest_greater_element(A): 
    """Return an array of smallest element on right side of each element""" 
    top = max(A) + 1 
    M = [-1] * top # M will contain the index of each element sorted by rank 
    for i,a in enumerate(A): 
     M[a] = i 
    N = next_greater_element(M) # N contains an index to the next element with higher value (-1 if none) 
    return [N[a] for a in A] 


A=[8,20,9,6,15,31] 
print smallest_greater_element(A) 

Chodzi o to, aby znaleźć następny element w celu zwiększenia wielkości z indeksem. Ten następny element będzie zatem najmniejszy, pojawiający się po prawej stronie.