3206 - Nr Inversiuni: Difference between revisions

From Bitnami MediaWiki
 
Line 35: Line 35:
== Rezolvare ==
== Rezolvare ==
<syntaxhighlight lang="python3" line="1">
<syntaxhighlight lang="python3" line="1">
def count_inversions(arr):
def este_permutare_valida(n, permutare):
    if n != len(permutare):
        return False
 
    elemente_unice = set(permutare)
    return len(elemente_unice) == n and all(1 <= elem <= n for elem in elemente_unice)
 
def numara_inversiuni(arr):
     if len(arr) <= 1:
     if len(arr) <= 1:
         return arr, 0
         return arr, 0


     mid = len(arr) // 2
     mijloc = len(arr) // 2
     left, left_inversions = count_inversions(arr[:mid])
     stanga, inversiuni_stanga = numara_inversiuni(arr[:mijloc])
     right, right_inversions = count_inversions(arr[mid:])
     dreapta, inversiuni_dreapta = numara_inversiuni(arr[mijloc:])
 
    merged, split_inversions = merge_and_count(left, right)


     total_inversions = left_inversions + right_inversions + split_inversions
     concatenat, inversiuni_split = combina_si_numara(stanga, dreapta)


     return merged, total_inversions
     inversiuni_totale = inversiuni_stanga + inversiuni_dreapta + inversiuni_split


    return concatenat, inversiuni_totale


def merge_and_count(left, right):
def combina_si_numara(stanga, dreapta):
     merged = []
     concatenat = []
     split_inversions = 0
     inversiuni_split = 0
     i = j = 0
     i = j = 0


     while i < len(left) and j < len(right):
     while i < len(stanga) and j < len(dreapta):
         if left[i] <= right[j]:
         if stanga[i] <= dreapta[j]:
             merged.append(left[i])
             concatenat.append(stanga[i])
             i += 1
             i += 1
         else:
         else:
             merged.append(right[j])
             concatenat.append(dreapta[j])
             split_inversions += len(left) - i
             inversiuni_split += len(stanga) - i
             j += 1
             j += 1


     merged.extend(left[i:])
     concatenat.extend(stanga[i:])
     merged.extend(right[j:])
     concatenat.extend(dreapta[j:])
 
    return merged, split_inversions


    return concatenat, inversiuni_split


if __name__ == "__main__":
if __name__ == "__main__":
     n = int(input("Introduceți numărul n: "))
     n = int(input("Introduceți numărul n: "))
     permutation = list(map(int, input("Introduceți permutarea: ").split()))
     permutare = list(map(int, input("Introduceți permutarea: ").split()))


     _, inversions = count_inversions(permutation)
     if este_permutare_valida(n, permutare):
        _, inversiuni = numara_inversiuni(permutare)
        print("Numărul inversiunilor permutării:", inversiuni)
    else:
        print("Permutarea introdusă nu este validă.")


    print("Numărul inversiunilor permutării:", inversions)


</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 11:23, 29 December 2023

Enunt[edit | edit source]

Se dă șirul a1, a2, …, an care este o permutare a mulțimii {1, 2, ..., n}. O inversiune în permutare este o pereche (i, j) cu proprietatea că i < j și a[i] > a[j].

Cerinta[edit | edit source]

Să se determine numărul inversiunilor permutării.

Date de intrare[edit | edit source]

Programul citește de la tastatură numărul n, iar apoi n numere naturale, separate prin spații, reprezentând permutarea.

Date de iesire[edit | edit source]

Programul va afișa pe ecran numărul S, reprezentând numărul inversiunilor permutării.

Restrictii si precizari[edit | edit source]

  • 1 ⩽ n ⩽ 100.000

Exemplul 1[edit | edit source]

Intrare
5
4 2 5 1 3
Iesire
Datele introduse corespund restrictiilor impuse
6

Exemplul 2[edit | edit source]

Intrare
5
-2 8 0 3
Iesire
Datele introduse nu corespund restrictiilor impuse

Rezolvare[edit | edit source]

<syntaxhighlight lang="python3" line="1"> def este_permutare_valida(n, permutare):

   if n != len(permutare):
       return False
   elemente_unice = set(permutare)
   return len(elemente_unice) == n and all(1 <= elem <= n for elem in elemente_unice)

def numara_inversiuni(arr):

   if len(arr) <= 1:
       return arr, 0
   mijloc = len(arr) // 2
   stanga, inversiuni_stanga = numara_inversiuni(arr[:mijloc])
   dreapta, inversiuni_dreapta = numara_inversiuni(arr[mijloc:])
   concatenat, inversiuni_split = combina_si_numara(stanga, dreapta)
   inversiuni_totale = inversiuni_stanga + inversiuni_dreapta + inversiuni_split
   return concatenat, inversiuni_totale

def combina_si_numara(stanga, dreapta):

   concatenat = []
   inversiuni_split = 0
   i = j = 0
   while i < len(stanga) and j < len(dreapta):
       if stanga[i] <= dreapta[j]:
           concatenat.append(stanga[i])
           i += 1
       else:
           concatenat.append(dreapta[j])
           inversiuni_split += len(stanga) - i
           j += 1
   concatenat.extend(stanga[i:])
   concatenat.extend(dreapta[j:])
   return concatenat, inversiuni_split

if __name__ == "__main__":

   n = int(input("Introduceți numărul n: "))
   permutare = list(map(int, input("Introduceți permutarea: ").split()))
   if este_permutare_valida(n, permutare):
       _, inversiuni = numara_inversiuni(permutare)
       print("Numărul inversiunilor permutării:", inversiuni)
   else:
       print("Permutarea introdusă nu este validă.")


</syntaxhighlight>

Explicatie[edit | edit source]

Cele 6 inversiuni sunt date de perechile de indici (1,2), (1,4), (1,5), (2,4), (3,4), (3,5).