IlmHamroh
JavaScript Full-stack/14-qism. Algoritmlar va ma'lumotlar tuzilmalari12/60-dars21 daqiqa
Mundarija (29)

Matritsa bilan ishlash: 2D massivni aylanish, spiral, 90° burish va yo'nalish massivi

Qisqacha: Matritsa — massivlar massivi: grid[r][c] — r-qator, c-ustun. Uni Array.from({ length: rows }, () => new Array(cols).fill(0)) bilan yarating (fill(new Array(...)) hamma qatorni bitta massivga aylantiradi). Hamma katakni aylanish — O(qatorlar × ustunlar); qatorma-qator yurish ustunma-ustundan bir necha baravar tez (protsessor keshi). Spiral — to'rt chegarani ichkariga qisqartirish; 90° burish — transpozitsiya + har qatorni teskari, joyida, O(n²). Qo'shni kataklar uchun yo'nalish massivi [[-1, 0], [1, 0], [0, -1], [0, 1]] va chegarani tekshirish.

Bu darsda

  • 2D massivni to'g'ri yaratasiz va qator hamda ustun bo'yicha aylanasiz.
  • Qatorma-qator va ustunma-ustun aylanish tezligi nega farq qilishini o'lchab ko'rasiz.
  • Matritsani spiral tartibda o'qiysiz, transpozitsiya qilasiz va 90° ga joyida burasiz.
  • Yo'nalish massivi bilan qo'shni kataklarni chegaradan chiqmasdan tekshirasiz.

Oldin bilishingiz kerak: Matn algoritmlari, Massiv xotirada va joyida amallar, Prefix sum (2D), fill va Array.from, Massiv destructuring.

1. Nega bu kerak?

«Bahor» zali kengaydi: endi 3 qator, har qatorda 4 tadan stol. Jasur aka planshetda zal sxemasini xohlaydi: qaysi stol bo'sh, qaysi band. Sardor uni matritsa (matrix) — massivlar massivi — sifatida saqlaydi: har qator — massiv, butun zal — qatorlar massivi. Maktab daftaridagi katakli jadvalni eslang: har katakning qatori va ustuni bor. Uni ikki o'lchovli (2D) massiv ham deyishadi.

Keyin talablar ketma-ket keldi:

  • "Ofitsiant zalni chetdan boshlab aylanib chiqsin — qaysi tartibda?"
  • "Planshetni yonboshiga qo'ysam, sxema ham burilsin."
  • "Bobur faqat klaviatura bilan ishlaydi — strelkalar bilan stoldan stolga o'tsin, lekin zaldan tashqariga 'chiqib ketmasin'."
  • "Har bo'sh stol yonida nechta bo'sh stol bor — katta guruhni qayerga o'tqazamiz?"

Ko'rinishidan har xil to'rt talab. Lekin bularning hammasi — matritsa masalalari. Ular algoritmlar dunyosida juda ko'p: o'yin taxtalari, rasm piksellari, xarita kataklari, jadval (Excel). Keyinchalik graflarda BFS va DFS va 2D dinamik dasturlash aynan shu tuzilmada ishlaydi. Bugun asosiy "harakatlarni" o'rganamiz.

2. Matritsa yaratish va aylanish

2.1 Yaratish va tuzog'i

Matritsani qo'lda yozish mumkin:

js
const hall = [
  [0, 1, 0, 0], // 0-qator: 0 — bo'sh, 1 — band
  [1, 1, 0, 1],
  [0, 0, 0, 1],
];
console.log(hall[1][2]); // 0 — 1-qator, 2-ustun bo'sh
console.log(hall.length, hall[0].length); // 3 4

hall[r][c] — avval qator (r, row), keyin ustun (c, column). Qatorlar soni — hall.length, ustunlar — hall[0].length. Bu tartibni hech qachon almashtirmang: koordinata (x, y) ga o'rgangan ko'z hall[x][y] yozishga moyil, lekin bu yerda birinchi indeks — vertikal (qator).

Katta matritsani dastur bilan yaratganda klassik tuzoq bor (Prefix sum darsida ogohlantirgan edik):

js
const bad = new Array(2).fill(new Array(3).fill(0));
bad[0][0] = 9;
console.log(bad); // [ [ 9, 0, 0 ], [ 9, 0, 0 ] ]

const good = Array.from({ length: 2 }, () => new Array(3).fill(0));
good[0][0] = 9;
console.log(good); // [ [ 9, 0, 0 ], [ 0, 0, 0 ] ]

fill ga bitta massiv berildi — u bir xil havolani hamma katakka yozdi (Havola semantikasi). Ikkala "qator" — bitta massiv. Array.from esa har qator uchun funksiyani qayta chaqiradi — har biri yangi massiv.

2.2 Qatorma-qator va ustunma-ustun

Hamma stolni ko'rib chiqish — ichma-ich ikki sikl. Ikki xil tartib bor:

js
const sales = [
  [3, 5, 2],
  [4, 1, 7],
];

// qatorma-qator: har qator ichida chapdan o'ngga
const byRows = [];
for (let r = 0; r < sales.length; r++) {
  for (let c = 0; c < sales[0].length; c++) byRows.push(sales[r][c]);
}

// ustunma-ustun: har ustun ichida yuqoridan pastga
const byCols = [];
for (let c = 0; c < sales[0].length; c++) {
  for (let r = 0; r < sales.length; r++) byCols.push(sales[r][c]);
}

console.log(byRows.join(" ")); // 3 5 2 4 1 7
console.log(byCols.join(" ")); // 3 4 5 1 2 7

Ikkalasi ham har katakni bir marta ko'radi: R qator va C ustun uchun O(R · C). Kvadrat n × n matritsada — O(n²). Bu "kvadratik" yomon degani emas: kirishning o'zi n² ta son, hammasini ko'rish shart.

2.3 O'lchov: tartib muhim

n × n matritsadagi hamma sonni ikki tartibda yig'dik (olcha, 5 o'lchov medianasi):

n × n Kataklar Qatorma-qator Ustunma-ustun
500 × 500 250 ming ≈ 0,22 ms ≈ 0,75 ms
1 000 × 1 000 1 mln ≈ 0,81 ms ≈ 5,0 ms
2 000 × 2 000 4 mln ≈ 3,8 ms ≈ 27 ms
4 000 × 4 000 16 mln ≈ 14 ms ≈ 182 ms

Qatorma-qator: n ikki baravar — vaqt to'rt baravar (× 3,8–4,6). Kataklar to'rt baravar ko'paydi — O(n²) aynan shuni kutadi. Ustunma-ustun ham O(n²), lekin har qadamda × 5–7 va 4 000 da 13 baravar sekin.

Sabab — Massiv xotirada darsidagi protsessor keshi. Har qator — xotirada uzluksiz turgan alohida massiv. Qatorma-qator yursangiz, keyingi son doim yonida — keshda tayyor. Ustunma-ustun yursangiz, har qadam boshqa qatorga, ya'ni xotiraning boshqa joyiga sakraydi. Kichik matritsa keshga to'liq sig'adi va farq kam. Katta matritsada har sakrash — RAM'ni kutish.

n × n matritsa yig'indisi: aylanish tartibi
Vaqt, ms
1820,225004 000nustunma-ustun: 500 → 0,75 msustunma-ustun: 1 000 → 5 msustunma-ustun: 2 000 → 27,13 msustunma-ustun: 4 000 → 182 msqatorma-qator: 500 → 0,22 msqatorma-qator: 1 000 → 0,81 msqatorma-qator: 2 000 → 3,77 msqatorma-qator: 4 000 → 14,32 ms
  • ustunma-ustun
  • qatorma-qator
n × n matritsa yig'indisi: aylanish tartibi
nustunma-ustunqatorma-qator
5000,75
1 0005
2 00027,13
4 000182
5000,22
1 0000,81
2 0003,77
4 00014,32

Manba: O'lchov: 12/32 dagi usul (har n alohida jarayonda, isitish, mediana), Node 24, i5-12500H; Node 24.21 (V8 13.6), Windows 11, 2026-10-06; massivlar massivi (butun sonlar), 5 o'lchov medianasi

Amaliy qoida: tartib muhim bo'lmasa (yig'indi, qidirish, nusxa) — qatorma-qator. Ustun bo'yicha natija kerak bo'lsa (har ustun yig'indisi), uni ham qatorma-qator yurib, colSums[c] += grid[r][c] bilan to'plash mumkin.

Tekshirib ko'ring: Jasur aka har ustunning (haftaning bir kuni) jami tushumini so'radi. Qatorma-qator yurib qanday hisoblaysiz?

Javob

Ustunlar soniga teng nollar massivi yasaymiz: const colSums = new Array(cols).fill(0). Keyin qatorma-qator yuramiz va har katakni o'z ustuniga qo'shamiz: colSums[c] += grid[r][c]. Vaqt yana O(R · C), qo'shimcha xotira O(C). Xotirani ketma-ket o'qiymiz — keshga mos.

3. Spiral tartib

Ofitsiant zalni chetdan boshlab, soat mili bo'yicha aylanib, markazga qarab yuradi. Stollar qaysi tartibda ko'riladi? Usul: to'rt chegara — top (eng yuqori ko'rilmagan qator), bottom, left, right. Har tomonni yurib bo'lgach, o'sha chegara bir qadam ichkariga suriladi:

Har stol bir marta ko'rildi — O(R · C) vaqt. Qo'shimcha xotira — natija massivi va to'rt son. Ikki if muhim. Matritsa kvadrat bo'lmasa (3 × 4), oxirgi aylanada bitta qator yoki ustun qoladi. Bu tekshiruvlarsiz o'sha qator ikki marta — avval chapdan o'ngga, keyin o'ngdan chapga — o'qilardi. 1-mashqda [[1, 2, 3]] (bitta qator) bilan sinab ko'ring.

4. Transpozitsiya va 90° burish

4.1 Transpozitsiya

Transpozitsiya (transpose) — qatorlarni ustunga, ustunlarni qatorga aylantirish: t[c][r] = m[r][c]. Haftalar × kunlar jadvali kunlar × haftalarga aylanadi. To'rtburchak matritsa uchun yangi matritsa kerak (o'lchami ham o'zgaradi):

js
function transpose(m) {
  return Array.from(
    { length: m[0].length },
    (_, c) => m.map((row) => row[c]), // c-ustun — yangi qator
  );
}

console.log(transpose([[1, 2, 3], [4, 5, 6]]));

Konsolda:

text
[ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]

2 × 3 → 3 × 2. O(R · C) vaqt va xotira.

4.2 90° ga joyida burish

Planshet yonboshiga qo'yildi — zal sxemasi soat mili bo'yicha 90° burilishi kerak. Kvadrat matritsa uchun buni joyida (in-place) qilish mumkin, ikki qadamda: transpozitsiya (diagonal bo'yicha almashtirish), keyin har qatorni teskari aylantirish. Kvadratda transpozitsiyani ham joyida qilsa bo'ladi: diagonaldan yuqoridagi har katak pastdagi "egizagi" bilan almashadi:

Nega aynan shu ikki qadam? Burishdan keyin chap ustun (yuqoridan pastga: 1, 4, 7) yuqori qatorga o'tadi, lekin teskari tartibda: 7, 4, 1. Transpozitsiya ustunni qatorga aylantiradi (1, 4, 7), teskari qilish tartibni to'g'rilaydi. Soat miliga qarshi burish uchun — avval qatorlarni teskari (yoki tartibini teskari), keyin transpozitsiya.

O'lchov (n × n, transpozitsiya + reverse):

n Vaqt Nisbat
500 ≈ 0,78 ms —
1 000 ≈ 4,8 ms × 6,2
2 000 ≈ 22 ms × 4,6
4 000 ≈ 148 ms × 6,6

n ikki baravar — kataklar to'rt baravar, vaqt 4,6–6,6 baravar. Ortiqchasi — yana kesh: transpozitsiya m[c][r] ni ustunma-ustun o'qiydi. Qo'shimcha xotira — O(1): 4 000 × 4 000 zal (16 million katak) uchun ikkinchi matritsa olmadik.

Tekshirib ko'ring: 90° ni to'rt marta burilsa nima bo'ladi? 180° burish uchun eng sodda yo'l qanday?

Javob

To'rt marta 90° — 360°, asl matritsa qaytadi. 180° uchun ikki marta burish shart emas: qatorlar tartibini teskari qilish (m.reverse()) va har qatorni teskari qilish (row.reverse()) yetadi. Bu ham O(n²), joyida.

5. Yo'nalish massivi: qo'shni kataklar

5.1 To'rt qo'shni

Har stolning to'rt qo'shnisi bor: yuqori (r − 1, c), past (r + 1, c), chap (r, c − 1), o'ng (r, c + 1). To'rtta deyarli bir xil if yozish o'rniga, siljishlarni massivga yozamiz — yo'nalish massivi (directions array). Har element — [qatorga qo'shiladigan son, ustunga qo'shiladigan son]: [-1, 0] — "bir qator yuqoriga, ustun o'sha". Keyin bitta sikl:

js
// yuqori, past, chap, o'ng
const DIRS = [[-1, 0], [1, 0], [0, -1], [0, 1]];

function freeNeighbors(hall, r, c) {
  let count = 0;
  for (const [dr, dc] of DIRS) {
    const nr = r + dr;
    const nc = c + dc;
    if (nr < 0 || nr >= hall.length) continue; // zaldan tashqari
    if (nc < 0 || nc >= hall[0].length) continue;
    if (hall[nr][nc] === 0) count++;
  }
  return count;
}

const hall = [
  [0, 1, 0, 0],
  [1, 1, 0, 1],
  [0, 0, 0, 1],
];
console.log(freeNeighbors(hall, 1, 2)); // 2
console.log(freeNeighbors(hall, 0, 0)); // 0
console.log(freeNeighbors(hall, 2, 3)); // 1

(1, 2) stolining qo'shnilari: yuqorida (0, 2) bo'sh, pastda (2, 2) bo'sh, chap va o'ngda band — 2. Burchakdagi (0, 0) stolning ikkita qo'shnisi zaldan tashqarida — ular continue bilan o'tkazildi.

5.2 Chegarani tekshirish nega shart?

Chegara tekshiruvisiz nima bo'ladi?

js
const hall = [
  [0, 1],
  [1, 0],
];
console.log(hall[0][5]); // undefined — jim
console.log(hall[5][0]); // xato

Konsolda:

text
undefined
TypeError: Cannot read properties of undefined (reading '0')

Tarjimasi: "Tur xatosi: aniqlanmagan qiymatning xususiyatini o'qib bo'lmaydi ('0' ni o'qishda)". Ikki xil xulq bor. Ustun chegaradan chiqsa (hall[0][5]), qator massivi undefined qaytaradi — jim xato: undefined === 0 yolg'on, va hisob noto'g'ri bo'lishi mumkin. Qator chegaradan chiqsa (hall[5] — undefined), undan [0] o'qishga urinish yiqitadi. Xabardagi '0' — biz o'qimoqchi bo'lgan ustun indeksi, xato aynan hall[5] ning undefined ekanida. Shuning uchun har ikkala indeksni tekshiring.

5.3 Sakkiz yo'nalish va Bobur

Diagonal qo'shnilar ham kerak bo'lsa (shaxmat shohi kabi), massivga to'rtta qator qo'shiladi: [-1, -1], [-1, 1], [1, -1], [1, 1]. Kod o'zgarmaydi — yo'nalish massivining afzalligi shu.

Bobur uchun klaviatura navigatsiyasi ham xuddi shu g'oya. Har strelka tugmasi — bitta siljish: ArrowUp — [-1, 0], ArrowDown — [1, 0], ArrowLeft — [0, -1], ArrowRight — [0, 1]. Yangi joy chegaradan chiqsa, fokus joyida qoladi. Klaviatura hodisalarini Klaviatura hodisalari darsida, fokusni boshqarishni Dinamik UI'da qulaylik darsida o'rgangan edingiz. Bu yerda faqat "qayerga o'tish" mantiqi — u DOM'siz, shuning uchun oson testlanadi.

6. Matritsani bitta massivda saqlash

Massivlar massivi qulay, lekin har qator — xotiraning alohida joyidagi alohida massiv. Ba'zan matritsa bitta uzun massivda saqlanadi: avval 0-qatorning hamma kataklari, keyin 1-qatorniki va shunday davom etadi. R × C matritsada (r, c) katak indeksi:

js
const R = 3;
const C = 4;
const flat = Array.from({ length: R * C }, (_, i) => i + 1); // 1..12
const at = (r, c) => flat[r * C + c];

console.log(at(1, 2), at(2, 3)); // 7 12
console.log(Math.floor(10 / C), 10 % C); // 2 2

r * C + c — oldingi r ta qatorda r · C ta katak bor, keyin shu qatorda c-katak. Teskari yo'l: indeks i dan qator — Math.floor(i / C), ustun — i % C (qoldiq operatori). 10-indeks — 2-qator, 2-ustun.

Nega kerak? Birinchidan, hamma kataklar haqiqatan uzluksiz — qatorlar orasida ham sakrash yo'q, kesh uchun eng yaxshi holat. Ikkinchidan, Typed arrays faqat bir o'lchovli: katta sonli matritsani Float64Array(R * C) da saqlash odatiy hol. Uchinchidan, brauzerning o'zi shunday qiladi: Canvas piksellari (ImageData.data) — bitta uzun massiv, har pikselda 4 ta son (qizil, yashil, ko'k, shaffoflik), indeks (r * width + c) * 4. Kamchiligi — o'qish qiyinroq va chegara tekshiruvi qo'lda: flat[r * C + c] da c = C bo'lsa, xato bermaydi — keyingi qatorning birinchi katagini qaytaradi.

Tekshirib ko'ring: 1920 × 1080 rasmda (kenglik 1920) 100-qator, 50-ustundagi pikselning qizil rangi ImageData.data ning qaysi indeksida?

Javob

(100 × 1920 + 50) × 4 = 768 200. Yashil — 768 201, ko'k — 768 202, shaffoflik — 768 203. Formulada kenglik (ustunlar soni) ishlatiladi, balandlik emas.

7. Chegaraviy holatlar

  • Bo'sh matritsa. [] — grid[0].length xato beradi (grid[0] — undefined). Funksiya boshida: if (grid.length === 0) return [];.
  • Bitta qator yoki bitta ustun. Spiral if lari aynan shu uchun. [[1, 2, 3]] → 1 2 3, [[1], [2], [3]] → 1 2 3.
  • To'rtburchak (kvadrat emas). Joyida 90° burish faqat kvadratda ishlaydi — R × C matritsa burilganda C × R bo'ladi, yangi matritsa kerak.
  • Qatorlar uzunligi har xil (jagged). grid[0].length hamma qator uchun to'g'ri emas. Ma'lumot tashqaridan kelsa — tekshiring.
  • Manfiy indeks. grid[-1] — undefined (xato emas). at(-1) esa oxirgi qatorni beradi — chegarani tekshirishda at ishlatmang.

8. Ko'p uchraydigan xatolar

8.1 fill bilan qatorlar

Bitta qatorni o'zgartirsangiz — hammasi o'zgaradi. Tuzatish: Array.from({ length: R }, () => new Array(C).fill(0)).

8.2 [x][y] va [r][c] chalkashligi

Birinchi indeks — qator (vertikal). Tuzatish: o'zgaruvchilarni r va c deb nomlang, x/y emas.

8.3 Faqat bitta chegarani tekshirish

hall[nr][nc] dan oldin faqat nr tekshirilsa — ustun chetida jim undefined. Tuzatish: ikkala indeks, ikkala tomon (< 0 va >= length).

8.4 Ustunma-ustun aylanish

Natija to'g'ri, lekin katta matritsada 10 baravardan ko'p sekin. Tuzatish: tartib muhim bo'lmasa — qatorma-qator.

9. Mashqlar

1-mashq (oson): Spiralni qo'lda

[[1, 2, 3]], [[1], [2], [3]] va [[1, 2], [3, 4]] uchun spiral tartibni yozing. Birinchi misolda qaysi if "qutqaradi"?

Yechim

1 2 3; 1 2 3; 1 2 4 3. Birinchi misolda: yuqori qator o'qilgach top = 1 > bottom = 0. Birinchi if (top <= bottom) yolg'on — pastki qator ikkinchi marta o'qilmaydi. Ikkinchi misolda o'ng ustun o'qilgach right = −1 < left = 0 — ikkinchi if chap ustunni qayta o'qishga yo'l qo'ymaydi.

2-mashq (o'rta): Ustunlar yig'indisi

columnTotals(grid) — har ustun yig'indisini qaytarsin, qatorma-qator yurib. [[3, 5, 2], [4, 1, 7]] → [7, 6, 9]. Bo'sh matritsa → [].

Yechim
js
function columnTotals(grid) {
  if (grid.length === 0) return [];
  const totals = new Array(grid[0].length).fill(0);
  for (const row of grid) {
    for (let c = 0; c < row.length; c++) totals[c] += row[c];
  }
  return totals;
}

console.log(columnTotals([[3, 5, 2], [4, 1, 7]])); // [ 7, 6, 9 ]
console.log(columnTotals([])); // []

for...of qatorlarni ketma-ket beradi, ichki sikl qator ichida chapdan o'ngga — xotirada ketma-ket. new Array(...).fill(0) bu yerda xavfsiz: fill ga son (primitiv) berildi, massiv emas.

3-mashq (qiyin): Matritsa funksiyalari testlari

kurs/mashqlar/14/12-matritsa/matritsa.test.mjs faylida darsdagi spiral (bo'sh matritsada []), rotate va freeNeighbors ni, hamda rotateCopy(m) ni yozing — u to'rtburchak matritsani ham 90° buradi (yangi matritsa qaytaradi). Testlar (node:test):

  1. spiral — 3 × 4 misol, bitta qator, bitta ustun, bo'sh.
  2. rotate to'rt marta — asl matritsa qaytadi (4 × 4); rotate natijasi rotateCopy bilan bir xil.
  3. rotateCopy 2 × 3 → 3 × 2, to'g'ri qiymatlar.
  4. freeNeighbors — burchak, chet va o'rtadagi stol; zaldan tashqariga chiqmaydi.

Ishora: rotateCopy uchun result[c][R - 1 - r] = m[r][c], result — C × R.

Yechim
js
// kurs/mashqlar/14/12-matritsa/matritsa.test.mjs
import { test } from "node:test";
import assert from "node:assert/strict";

function spiral(grid) {
  const result = [];
  if (grid.length === 0) return result;
  let top = 0;
  let bottom = grid.length - 1;
  let left = 0;
  let right = grid[0].length - 1;
  while (top <= bottom && left <= right) {
    for (let c = left; c <= right; c++) result.push(grid[top][c]);
    top++;
    for (let r = top; r <= bottom; r++) result.push(grid[r][right]);
    right--;
    if (top <= bottom) {
      for (let c = right; c >= left; c--) {
        result.push(grid[bottom][c]);
      }
      bottom--;
    }
    if (left <= right) {
      for (let r = bottom; r >= top; r--) result.push(grid[r][left]);
      left++;
    }
  }
  return result;
}

function rotate(m) {
  const n = m.length;
  for (let r = 0; r < n; r++) {
    for (let c = r + 1; c < n; c++) {
      [m[r][c], m[c][r]] = [m[c][r], m[r][c]];
    }
  }
  for (const row of m) row.reverse();
  return m;
}

function rotateCopy(m) {
  const R = m.length;
  const C = m[0].length;
  const result = Array.from({ length: C }, () => new Array(R));
  for (let r = 0; r < R; r++) {
    for (let c = 0; c < C; c++) result[c][R - 1 - r] = m[r][c];
  }
  return result;
}

const DIRS = [[-1, 0], [1, 0], [0, -1], [0, 1]];
function freeNeighbors(hall, r, c) {
  let count = 0;
  for (const [dr, dc] of DIRS) {
    const nr = r + dr;
    const nc = c + dc;
    if (nr < 0 || nr >= hall.length) continue;
    if (nc < 0 || nc >= hall[0].length) continue;
    if (hall[nr][nc] === 0) count++;
  }
  return count;
}

const square = (n) =>
  Array.from({ length: n }, (_, r) =>
    Array.from({ length: n }, (_, c) => r * n + c));

test("spiral — misol va chegaralar", () => {
  const tables = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
  const expected = [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7];
  assert.deepEqual(spiral(tables), expected);
  assert.deepEqual(spiral([[1, 2, 3]]), [1, 2, 3]);
  assert.deepEqual(spiral([[1], [2], [3]]), [1, 2, 3]);
  assert.deepEqual(spiral([]), []);
});

test("rotate: to'rt marta — asl, rotateCopy bilan bir xil", () => {
  const m = square(4);
  const copy = rotateCopy(square(4));
  assert.deepEqual(rotate(m), copy);
  rotate(m);
  rotate(m);
  rotate(m);
  assert.deepEqual(m, square(4));
});

test("rotateCopy — 2 × 3 dan 3 × 2", () => {
  const out = rotateCopy([[1, 2, 3], [4, 5, 6]]);
  assert.deepEqual(out, [[4, 1], [5, 2], [6, 3]]);
});

test("freeNeighbors — burchak, chet, o'rta", () => {
  const hall = [[0, 1, 0, 0], [1, 1, 0, 1], [0, 0, 0, 1]];
  assert.equal(freeNeighbors(hall, 0, 0), 0);
  assert.equal(freeNeighbors(hall, 2, 3), 1);
  assert.equal(freeNeighbors(hall, 1, 2), 2);
});

Papkada node --test ni ishga tushiring. Bizda (Node 24.21.0) shunday chiqdi — millisekundlar sizda boshqacha:

text
✔ spiral — misol va chegaralar (1.3168ms)
✔ rotate: to'rt marta — asl, rotateCopy bilan bir xil (1.1399ms)
✔ rotateCopy — 2 × 3 dan 3 × 2 (0.1531ms)
✔ freeNeighbors — burchak, chet, o'rta (0.9465ms)
ℹ tests 4
ℹ suites 0
ℹ pass 4
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 84.8696

Ikkinchi test ikki mustaqil yechimni bir-biriga solishtiradi: joyida rotate va nusxa bilan rotateCopy. Ikkalasi bir xil xato qilishi qiyin — bu "sodda yechim bilan solishtirish"ning yana bir ko'rinishi. "To'rt marta burish — asl" esa xususiyatga asoslangan test: javobni bilmasdan ham to'g'rilikni tekshiradi.

4-mashq: Amaliy tajriba — matritsa qatorlari

kurs/mashqlar/14/MURAKKABLIK.md ga bugungi yechimlarni qo'shing. Matritsa uchun n emas, ikki o'lchov: R (qatorlar) va C (ustunlar) — Kodning murakkabligini hisoblash darsidagi "ikki xil kirish" qoidasi.

Yechim
text
| Masala | Naqsh | Vaqt | Xotira |
|---|---|---|---|
| Hamma katak (qatorma-qator) | ichma-ich sikl | O(R · C) | O(1) |
| Spiral tartib | to'rt chegara | O(R · C) | O(1) + natija |
| Transpozitsiya | t[c][r] = m[r][c] | O(R · C) | O(R · C) |
| 90° burish (kvadrat) | transpozitsiya + reverse | O(n²) | O(1) |
| Qo'shni bo'sh stollar | yo'nalish massivi | O(1) har katak | O(1) |
bash
git add 14/MURAKKABLIK.md 14/12-matritsa
git commit -m "14/12: matritsa — spiral, burish, qo'shnilar"

10. Real ishda

  • Rasm va grafika. Rasm — piksellar matritsasi. Rasmni burish, aks ettirish, kesish — bugungi amallar. Canvas ImageData piksellarni bitta uzun massivda saqlaydi: index = (r * width + c) * 4 — matritsani "yoyib" saqlash.
  • O'yinlar va xaritalar. Shaxmat, "Minalar" (Minesweeper), labirint — yo'nalish massivi va chegara tekshiruvi. Yo'l topish — Graflarda BFS.
  • Jadvallar. Excel, Google Sheets, CSV — qatorlar va ustunlar; "ustun yig'indisi", "transpozitsiya" — tayyor funksiyalar.
  • Intervyu. LeetCode'dagi "Spiral Matrix", "Rotate Image", "Transpose Matrix", "Set Matrix Zeroes", "Game of Life" — eng mashhur matritsa masalalari. "Rotate Image" da shart odatda "joyida" deydi.

Xulosa

  • Matritsa — massivlar massivi, grid[r][c]: avval qator, keyin ustun. Array.from bilan yarating, fill(new Array()) bilan emas.
  • Hamma katakni aylanish — O(R · C). Qatorma-qator yurish keshga mos: 4 000 × 4 000 da ustunma-ustundan 13 baravar tez chiqdi.
  • Spiral — to'rt chegara ichkariga qisqaradi; bitta qator/ustun qolganda if lar takrorni to'xtatadi.
  • 90° burish = transpozitsiya + qatorlarni teskari: kvadratda joyida, O(n²) vaqt, O(1) xotira.
  • Yo'nalish massivi bitta siklda hamma qo'shnini beradi; ikkala indeksni ham chegaraga tekshiring.

Keyingi dars: Klassik chiziqli algoritmlar: Kadane, Boyer-Moore, Dutch flag — bir o'tishda eng katta yig'indili bo'lak, ko'pchilik element va uch rangli ajratish.

Manbalar

  • MDN: Array.from(), Array.prototype.fill() — developer.mozilla.org
  • MDN: ImageData — piksellar massivi — developer.mozilla.org
  • LeetCode masalalari: "Spiral Matrix", "Rotate Image", "Transpose Matrix" — leetcode.com (shartlar bu yerda o'zgartirib berilgan)
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Matritsa bilan ishlash: 2D massivni aylanish, spiral, 90° burish va yo'nalish massivi — IlmHamroh