2010-12-29 19 views
16

Powiel możliwe:
Counting inversions in an arrayJak znaleźć liczbę przewrotów w tablicy?

To phone interview question: "Znajdź liczbę inwersji w tablicy". Chyba mają na myśli rozwiązanie O (N log N). Wierzę, że nie może być lepsza niż O (N log N), ponieważ jest to złożoność sortowania.

Odpowiedzi do similar question można podsumować w następujący sposób:

  1. Oblicz połowę odległości elementów powinien być przeniesiony do sortowania tablicy: skopiowanie tablicy i sortowania kopię. Dla każdego elementu oryginalnej tablicy a[i] znajdź jego pozycję j w posortowanej kopii (wyszukiwanie binarne) i zsumuj połówki odległości abs(i - j)/2.
  2. Zmienić merge sort: modyfikować merge liczyć inwersje między dwoma posortowanych tablic i uruchomić regularne merge sort z tym zmodyfikowanym merge.

    Czy ma to sens? Czy istnieją inne (być może prostsze) rozwiązania? Czy nie jest to zbyt trudne dla rozmowy telefonicznej?

+1

Możesz znaleźć n log n rozwiązanie kodowane w języku Java tutaj: http: // stackoverflow.com/questions/337664/counting-inversions-in-an array/6424847 # 6424847 –

Odpowiedz

17

Jest to właściwie aplikacja do algorytmu dziel i rządź, a jeśli jesteś jej obeznany, możesz szybko znaleźć rozwiązanie.

Jako przykład podajemy [1 3 8 5 7 2 4 6], zakładamy, że mamy posortowaną tablicę jako [1 3 5 8] i [2 4 6 7], a teraz musimy połączyć te dwie tablice i uzyskać liczba całkowitych inwersji.

Ponieważ mamy już liczbę inwersji w każdej z tablic podrzędnych, musimy jedynie ustalić liczbę inwersji spowodowanych scalaniem tablic. Za każdym razem, gdy element zostanie wstawiony, na przykład, 2 wstawiony do [1 # 3 5 8], możesz wiedzieć, ile jest odwrotności między pierwszą tablicą a elementem 2 (3 pary w tym przykładzie). Następnie możesz je dodać, aby uzyskać liczbę inwersji spowodowanych połączeniem.

+0

Daj nam znać liczbę inwersji dla 2 połówek tablicy. Jak mógłbyś je połączyć, aby uzyskać liczbę inwersji całej tablicy? – Michael

+0

@ Michael Poprawiłem moją odpowiedź – ZelluX

+0

Dzięki za aktualizację. Jak rozumiem, sztuczka polega na tym, aby obie podprzestrzennie były sortowane. Oznacza to, że możemy zliczać inwersje w każdej z pod-tablic, ale aby uzyskać całkowitą liczbę inwersji, musimy je posortować. – Michael

4

Można również użyć liczenia sort-podobnego podejścia, jeśli tablica zawiera tylko małe ilości na przykład (jak jeśli jest to tablica znaków):

inversions = 0 
let count = array of size array.Length 
for i = 0 to array.Length - 1 do 
    for j = array[i] + 1 to maxArrayValue do 
     inversions = inversions + count[j] 

    count[array[i]] = count[array[i]] + 1 

Zasadniczo zachować rachubę, ile razy każdy pojawia się element. Następnie na każdym kroku i liczba inwersji generowanych przez element i jest równa sumie wszystkich elementów większych niż i, które pochodzą przed i, które można łatwo obliczyć przy użyciu liczby, którą przechowujesz.

To będzie O(n*eps), gdzie eps jest domeną elementów w twojej tablicy.

Jest to zdecydowanie prostsze w mojej opinii. Jeśli chodzi o efektywność, to dobrze, jeśli tylko eps jest mały. Jeśli tak, to powinno być szybsze niż inne podejścia, ponieważ nie ma rekurencji.

Powiązane problemy