🔲 Matrici

Capitolul 5 — Parcurgere, diagonale, transpusă, rotire, matrice pătratice speciale și probleme BAC

MatriciDiagonaleTranspusăSpiralăTablouri 2D
📖 12 min
0
📋

Declararea și citirea matricelor

O matrice (tablou bidimensional) stochează date în rânduri și coloane, accesate prin doi indici: a[linie][coloana].

int a[101][101];  // matrice de maxim 100×100
int n, m;       // n linii, m coloane

// Citire
cin >> n >> m;
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        cin >> a[i][j];

// Afișare
for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= m; j++)
        cout << a[i][j] << " ";
    cout << endl;
}
Memorie: O(n×m)

Stocată pe linii în RAM (row-major order)

Acces element: O(1)

a[i][j] — acces direct prin indici

🔁

Parcurgere — sumă, minim, maxim

Suma elementelor pe linii și coloane

// Suma tuturor elementelor
int suma = 0;
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        suma += a[i][j];

// Suma pe fiecare linie
for (int i = 1; i <= n; i++) {
    int sumaLinie = 0;
    for (int j = 1; j <= m; j++)
        sumaLinie += a[i][j];
    cout << "Suma linia " << i << ": " << sumaLinie << endl;
}

Minimul și poziția sa

int minim = a[1][1], linMin = 1, colMin = 1;
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        if (a[i][j] < minim) {
            minim = a[i][j];
            linMin = i; colMin = j;
        }
Complexitate parcurgere completă: O(n×m) — sau O(n²) pentru matrice pătratică n×n.
📐

Diagonalele matricei pătratice

Pentru matrice pătratică n×n (indexată de la 1):
Diagonala principală: elemente unde i == j
Diagonala secundară: elemente unde i + j == n + 1
Atenție — două convenții de indexare!
IndexareDiagonala principalăDiagonala secundarăExemplu n=5
de la 1 (BAC, standard) i == j i + j == n + 1 (1,5),(2,4),(3,3),(4,2),(5,1) — suma i+j = 6 = n+1
de la 0 (C++ array) i == j i + j == n - 1 (0,4),(1,3),(2,2),(3,1),(4,0) — suma i+j = 4 = n-1

La BAC se folosește exclusiv indexarea de la 1. Condiția pentru diagonala secundară este i + j == n + 1, iar accesul în cod este a[i][n-i+1].

// Suma diagonalei principale
int sumaDiagP = 0;
for (int i = 1; i <= n; i++)
    sumaDiagP += a[i][i];

// Suma diagonalei secundare
int sumaDiagS = 0;
for (int i = 1; i <= n; i++)
    sumaDiagS += a[i][n-i+1];

Triunghiul superior și inferior

// Suma elementelor DEASUPRA diagonalei principale (triunghi superior)
int sumaSup = 0;
for (int i = 1; i <= n; i++)
    for (int j = i+1; j <= n; j++)  // j > i
        sumaSup += a[i][j];

// Suma elementelor SUB diagonala principală (triunghi inferior)
int sumaInf = 0;
for (int i = 1; i <= n; i++)
    for (int j = 1; j < i; j++)  // j < i
        sumaInf += a[i][j];
Proprietate: Suma totală = sumaDiagP + sumaSup + sumaInf (dacă diagonalele nu se suprapun)
↔️

Transpusa matricei

Transpusa matricei A este matricea B unde B[i][j] = A[j][i] — liniile devin coloane și viceversa.

// Transpusa în matrice separată (funcționează și pentru dreptunghice)
int t[101][101];  // t are m linii și n coloane
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        t[j][i] = a[i][j];
// Transpusa IN-PLACE pentru matrice PĂTRATICĂ (n×n)
for (int i = 1; i <= n; i++)
    for (int j = i+1; j <= n; j++)
        swap(a[i][j], a[j][i]);  // interschimbăm deasupra diagonalei
Exemplu:
A = [[1,2,3],[4,5,6]] → Aᵀ = [[1,4],[2,5],[3,6]]
🔄

Rotirea matricei cu 90°

Rotirea unei matrice n×n cu 90° în sens orar: b[j][n-i+1] = a[i][j]

// Rotire 90° sens orar (Clockwise)
int b[101][101];
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
        b[j][n-i+1] = a[i][j];

// Rotire 90° sens antiorar (Counter-Clockwise)
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
        b[n-j+1][i] = a[i][j];
Rotire 180° = rotire 90° aplicată de două ori, sau direct: b[n-i+1][n-j+1] = a[i][j]

Matrice pătratice speciale

Matrice simetrică față de diagonala principală

bool esteSimetrica = true;
for (int i = 1; i <= n && esteSimetrica; i++)
    for (int j = 1; j < i; j++)
        if (a[i][j] != a[j][i]) esteSimetrica = false;

Matrice cu borduri (cadru)

// Suma elementelor de pe bordul matricei
int sumaBord = 0;
for (int j = 1; j <= m; j++) sumaBord += a[1][j] + a[n][j];  // liniile 1 și n
for (int i = 2; i < n; i++)  sumaBord += a[i][1] + a[i][m];   // coloanele 1 și m

Umplere cu 0 a bordurilor

for (int j = 1; j <= m; j++) a[1][j] = a[n][j] = 0;
for (int i = 1; i <= n; i++) a[i][1] = a[i][m] = 0;

Matrice identitate

// Creare matrice identitate n×n
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
        a[i][j] = (i == j) ? 1 : 0;
🌀

Parcurgere în spirală

Problemă clasică: Parcurgeți și afișați elementele matricei în ordine spirală (exterior → interior, sens orar).
void spirala(int a[][101], int n, int m) {
    int top = 1, bot = n, left = 1, right = m;

    while (top <= bot && left <= right) {
        for (int j = left; j <= right; j++)  cout << a[top][j] << " ";  top++;
        for (int i = top; i <= bot; i++)    cout << a[i][right] << " ";  right--;
        if (top <= bot) {
            for (int j = right; j >= left; j--) cout << a[bot][j] << " ";  bot--;
        }
        if (left <= right) {
            for (int i = bot; i >= top; i--)   cout << a[i][left] << " ";   left++;
        }
    }
}
Exemplu n=3: [[1,2,3],[4,5,6],[7,8,9]] → 1 2 3 6 9 8 7 4 5
🔢

Demo Interactiv — Zone Matrice 5×5

🗺️ Cum recunosc zonele în matrice?

O matrice pătratică n×n are mai multe zone speciale. Elementul de pe linia i și coloana j aparține:

  • Diagonalei principale dacă i == j
  • Diagonalei secundare dacă i + j == n + 1
  • Triunghiului superior dacă j > i
  • Triunghiului inferior dacă j < i
  • Bordurii dacă i==1 || i==n || j==1 || j==n

Apasă butoanele de mai jos pentru a vedea evidențiată fiecare zonă:

Diag. principală
Diag. secundară
Ambele diagonale
Triunghi superior
Triunghi inferior
Bordură
📝

Probleme tip BAC — matrici

Problemă 1 (BAC 2023): Dată o matrice pătratică n×n, verificați dacă este matrice magică (suma pe orice linie, coloană sau diagonală este aceeași).
Soluție:
bool esteMagica(int a[][101], int n) {
    int suma = 0;
    for (int i=1; i<=n; i++) suma += a[1][i];  // suma primei linii
    for (int i=2; i<=n; i++) {
        int s=0; for (int j=1;j<=n;j++) s+=a[i][j];
        if(s!=suma) return false;
    }
    for (int j=1; j<=n; j++) {
        int s=0; for (int i=1;i<=n;i++) s+=a[i][j];
        if(s!=suma) return false;
    }
    int d1=0, d2=0;
    for (int i=1;i<=n;i++) { d1+=a[i][i]; d2+=a[i][n-i+1]; }
    return (d1==suma && d2==suma);
}
Problemă 2: Dată o matrice n×m, rotiți toate elementele de pe borduri cu o poziție în sens orar (fără elementele interioare).
Indiciu: Salvați elementul din colțul stânga-sus, deplasați liniile și coloanele de margine pe rând, restaurați elementul salvat.
💪

Exerciții interactive — testează cunoștințele