Přeskočit na obsah
TypeScript Ace

Tahák

Všechno důležité na jednom místě

Typy, metody a vzory, které na LeetCode použiješ nejčastěji. Kód zkopíruješ jedním klikem, celý tahák si můžeš vytisknout.

1

Základní typy

Lekce 1

Primitivní typy

const n: number = 42;          // celá i desetinná číslaconst s: string = "ahoj";const ok: boolean = true;const big: bigint = 2n ** 64n;  // obří celá číslalet nothing: null = null;       // záměrně „nic“let notSet: undefined;          // hodnota nenastavená

Odvození typu

let count = 10;              // TS ví, že je to numberconst name = "Eva";          // typ "Eva" (konstanta)const empty: number[] = [];  // prázdné hodnoty otypujconst seen = new Set<string>();

Typy piš u parametrů funkcí a u prázdných polí, map a setů. Jinde je TS odvodí sám.

Union a literal typy

let id: number | string = 1;   // jedno NEBO druhéid = "abc";type Dir = "up" | "down" | "left" | "right";let maybe: number | null = null;

Zúžení typu (narrowing)

function f(v: number | string | null) {  if (v === null) return 0;                  // null  if (typeof v === "number") return v * 2;   // number  return v.length;                           // zbývá string}

Testy typu za běhu

typeof v === "string"   // "number", "boolean", "object", …Array.isArray(v)        // je to pole?v instanceof Map        // instance třídy?"radius" in shape       // má vlastnost?

any vs unknown

let a: any = 1;       // vypne kontrolu – nepoužívejlet u: unknown = 1;   // „nevím“ – nejdřív ověřif (typeof u === "number") u.toFixed(1);

Operátory ?? ?. a !

const name = input ?? "host";      // jen pro null/undefinedconst n = count || 10;             // pozor: i pro 0 a ""const city = user?.address?.city;  // undefined místo páduconst age = ages.get("eva")!;      // „věř mi, není undefined“

Převody

Number("42");          // 42parseInt("42px", 10);  // 42String(42);            // "42"(10).toString(2);      // "1010" – binárněparseInt("1010", 2);   // 10(3.14159).toFixed(2);  // "3.14"

PastFalsy hodnoty

// falsy: false, 0, -0, 0n, "", null, undefined, NaN// všechno ostatní je truthy – i tohle:Boolean("0");  // trueBoolean([]);   // trueBoolean({});   // true

Prázdné pole testuj přes arr.length === 0, ne přes !arr.

PastPorovnávej přes ===

a === b   // ✅ přísná rovnosta !== b   // ✅a == b    // ❌ převádí typy: 0 == "" je true
2

Pole

Lekce 2

Vytvoření

const a: number[] = [1, 2, 3];const zeros = new Array<number>(n).fill(0);const range = Array.from({ length: n }, (_, i) => i); // 0 … n-1const copy = [...a];

2D pole (matice, DP tabulka)

const dp = Array.from({ length: rows }, () =>  new Array<number>(cols).fill(0),);dp[r][c] = 1;const m = grid.length;     // počet řádkůconst n = grid[0].length;  // počet sloupců

Přidat a odebrat

a.push(x);          // na konec         O(1)a.pop();            // z konce          O(1)a.unshift(x);       // na začátek       O(n)a.shift();          // ze začátku       O(n)a.splice(i, 1);     // smaž prvek na i  O(n)a.splice(i, 0, x);  // vlož x na i      O(n)

pop() a shift() vrací T | undefined – pole může být prázdné.

Přístup

a[0];             // prvnía[a.length - 1];  // poslednía.at(-1);         // poslední (kratší zápis)a.length;         // počet prvkůa[99];            // undefined – nespadne

Hledání

a.includes(x);              // true / falsea.indexOf(x);               // index, nebo -1a.find((v) => v > 5);       // prvek, nebo undefineda.findIndex((v) => v > 5);  // index, nebo -1a.findLast((v) => v > 5);   // hledá od koncea.some((v) => v < 0);       // aspoň jeden?a.every((v) => v > 0);      // všechny?

Transformace (vrací nové pole)

a.map((v, i) => v * 2);a.filter((v) => v % 2 === 0);a.reduce((acc, v) => acc + v, 0);a.slice(1, 3);         // indexy 1 a 2 (3 už ne)a.slice(-2);           // poslední dva[...a, ...b];          // spojení[[1], [2, 3]].flat();  // [1, 2, 3]

Řazení

a.sort((x, y) => x - y);   // vzestupně – MĚNÍ polea.sort((x, y) => y - x);   // sestupněconst s = a.toSorted((x, y) => x - y);  // nová kopiewords.sort((x, y) => x.localeCompare(y));pairs.sort((p, q) => p[0] - q[0] || p[1] - q[1]);

Poslední řádek řadí podle prvního prvku a při shodě podle druhého.

Pastsort() bez funkce řadí jako text

[10, 1, 5].sort();                 // [1, 10, 5] ❌[10, 1, 5].sort((a, b) => a - b);  // [1, 5, 10] ✅

Procházení

for (let i = 0; i < a.length; i++) {}  // s indexemfor (const v of a) {}                  // hodnotyfor (const [i, v] of a.entries()) {}   // index i hodnotaa.forEach((v, i) => {});               // nejde break!

for...in u polí nepoužívej – dává indexy jako stringy.

Destructuring a prohození

const [first, second, ...rest] = a;[a[i], a[j]] = [a[j], a[i]];   // prohodí dva prvkylet x = 1, y = 2;[x, y] = [y, x];

Tuple

const p: [number, number] = [3, 4];const [x, y] = p;const intervals: [number, number][] = [[1, 3], [2, 6]];const pair: [string, number] = ["věk", 25];

Další užitečné

a.reverse();      // otočí – MĚNÍ polea.join(", ");     // "1, 2, 3"a.fill(0);        // vyplní – MĚNÍ poleMath.max(...a);   // maximuma.length = 0;     // vyprázdní pole

Pastfill s polem = sdílený odkaz

const bad = new Array(3).fill([]);  // ❌ 3× tentýž objektbad[0].push(1);                     // [[1], [1], [1]]const good = Array.from({ length: 3 }, (): number[] => []); // ✅
3

Stringy

Lekce 3

Základy

s.length;s[0];              // první znaks.at(-1);          // poslední znaks.charAt(i);`Ahoj, ${name}!`  // template string

Hledání

s.includes("ab");    // true / falses.indexOf("a");      // první výskyt, nebo -1s.lastIndexOf("a");  // poslední výskyts.startsWith("He");s.endsWith("lo");

Podřetězce

s.slice(0, 3);      // znaky 0, 1, 2s.slice(-3);        // poslední 3s.slice(2);         // od indexu 2 do konces.substring(1, 4);  // jako slice, bez záporných indexů

Úpravy (vrací nový string)

s.toUpperCase();s.toLowerCase();s.trim();                // ořízne mezery na krajíchs.replace("a", "b");     // první výskyts.replaceAll("a", "b");  // všechny výskyty"ab".repeat(3);          // "ababab""7".padStart(3, "0");    // "007"

String ↔ pole

s.split("");                 // pole znaků[...s];                      // totéžs.split(" ");                // slovas.trim().split(/\s+/);       // slova i přes víc mezerchars.join("");              // zpět na string[...s].reverse().join("");   // otočení

Znaky a ASCII

"a".charCodeAt(0);        // 97String.fromCharCode(98);  // "b"c.charCodeAt(0) - 97;     // pořadí písmene 0–25 const cnt = new Array<number>(26).fill(0);for (const c of s) cnt[c.charCodeAt(0) - 97]++;

Testy znaků

c >= "0" && c <= "9";    // číslice/[a-z]/i.test(c);        // písmeno/[a-z0-9]/i.test(c);     // písmeno nebo číslicec === c.toUpperCase();   // velké písmeno

Porovnání

"apple" < "banana";          // true (podle abecedy)a.localeCompare(b);          // -1 / 0 / 1 – do sort"10" < "9";                  // true! porovnává se textNumber("10") < Number("9");  // false

Čísla ↔ string

String(4096).length;                 // počet cifer: 4String(4096).split("").map(Number);  // [4, 0, 9, 6]Number("123") + 1;                   // 124"5" + 1;                             // "51" – pozor!

PastStringy jsou neměnné

s[0] = "H";            // ❌ nejdeconst arr = [...s];arr[0] = "H";s = arr.join("");      // ✅

Při skládání v cyklu sbírej kousky do pole a nakonec zavolej join("").

4

Objekty a typy

Lekce 4

type a interface

type Person = {  name: string;  age?: number;          // volitelné  readonly id: number;   // jen pro čtení};interface Animal {  name: string;  sound(): string;       // metoda}interface Dog extends Animal { breed: string }

Kombinace typů

type Id = number | string;     // jedno NEBO druhétype Both = HasId & HasName;   // musí mít obojítype Shape =  | { kind: "circle"; r: number }  | { kind: "rect"; w: number; h: number };// switch (shape.kind) → TS pozná, která varianta to je

Slovník

const scores: Record<string, number> = {};scores["eva"] = 10;const ages: { [name: string]: number } = {};

Na LeetCode je většinou lepší Map – viz sekce Map a Set.

Práce s objekty

Object.keys(o);     // ["a", "b"]Object.values(o);   // [1, 2]Object.entries(o);  // [["a", 1], ["b", 2]]"a" in o;           // existuje klíč?for (const [k, v] of Object.entries(o)) {}

Kopie a destructuring

const { name, age } = person;const { id, ...others } = person;     // vše kromě idconst copy = { ...person, age: 31 };  // mělká kopieconst deep = structuredClone(obj);    // hluboká kopie

Utility typy

Partial<Person>        // vše volitelnéRequired<Person>       // vše povinnéReadonly<Person>       // vše jen pro čteníPick<Person, "name">   // jen vybrané klíčeOmit<Person, "id">     // bez vybraných klíčůReturnType<typeof fn>  // návratový typ funkce

PastObjekty a pole jsou odkazy

const a = { v: 1 };const b = a;        // tentýž objekt, ne kopie!b.v = 99;           // a.v je teď taky 99[1, 2] === [1, 2];  // false – dva různé objekty
5

Funkce

Lekce 5

Zápis funkce

function add(a: number, b: number): number {  return a + b;}const mul = (a: number, b: number) => a * b;const sq = (x: number) => {  return x * x;   // se { } je return nutný};

Parametry

function f(a: number, b = 10, c?: string) {}  // výchozí, volitelnýfunction sum(...nums: number[]) {}            // libovolný početfunction g({ x, y }: { x: number; y: number }) {}

Návratové typy

function log(msg: string): void {}              // nic nevracífunction find(): number | null { return null; } // může vrátit „nic“function minMax(a: number[]): [number, number] {  return [Math.min(...a), Math.max(...a)];}function fail(msg: string): never { throw new Error(msg); }

Funkce jako parametr

type Op = (a: number, b: number) => number;function apply(op: Op, a: number, b: number): number {  return op(a, b);}apply((x, y) => x - y, 5, 3);  // 2

Generika

function first<T>(arr: T[]): T | undefined {  return arr[0];}first([1, 2]);   // number | undefinedfirst(["a"]);    // string | undefinedconst m = new Map<string, number[]>();

Vnořená funkce (DFS)

function countPaths(n: number): number {  let count = 0;  const dfs = (i: number): void => {    if (i > n) return;    if (i === n) { count++; return; }    dfs(i + 1);    dfs(i + 2);  };  dfs(0);  return count;}

Vnořená funkce vidí proměnné té vnější (closure), takže je nemusíš předávat.

Memoizace

const memo = new Map<number, number>();function fib(n: number): number {  if (n <= 1) return n;  if (memo.has(n)) return memo.get(n)!;  const r = fib(n - 1) + fib(n - 2);  memo.set(n, r);  return r;}

PastArrow funkce se { } potřebuje return

const a = (x: number) => x * 2;      // ✅ vrací x * 2const b = (x: number) => { x * 2 };  // ❌ vrací undefinedconst c = () => ({ ok: true });      // objekt obal do ( )
6

Map a Set

Lekce 6

Set – unikátní hodnoty

const set = new Set<number>();set.add(1);set.has(1);       // true – O(1)set.delete(1);set.size;const unique = [...new Set(arr)];  // bez duplicitfor (const v of set) {}

Map – klíč → hodnota

const map = new Map<string, number>();map.set("a", 1);map.get("a");      // 1 | undefinedmap.has("a");      // O(1)map.delete("a");map.size;for (const [key, value] of map) {}[...map.keys()];  [...map.values()];

Počítání výskytů

const freq = new Map<string, number>();for (const c of s) {  freq.set(c, (freq.get(c) ?? 0) + 1);}

Kontrola duplicit

const seen = new Set<number>();for (const n of nums) {  if (seen.has(n)) return true;  seen.add(n);}return false;

Seskupování

const groups = new Map<string, string[]>();for (const w of words) {  const key = [...w].sort().join("");  if (!groups.has(key)) groups.set(key, []);  groups.get(key)!.push(w);}[...groups.values()];

Seřazení podle počtu

const byCount = [...freq.entries()].sort((a, b) => b[1] - a[1]);const topK = byCount.slice(0, k).map(([key]) => key);

PastPole jako klíč nefunguje

const s = new Set<number[]>();s.add([1, 2]);s.has([1, 2]);             // false ❌ jiné poleconst keys = new Set<string>();keys.add(`${r},${c}`);    // ✅ klíč jako string

Map a Set porovnávají pole a objekty podle odkazu, ne podle obsahu.

7

Třídy a struktury

Lekce 7

Třída

class Counter {  private count = 0;       // jen uvnitř třídy  readonly name: string;   // jen pro čtení  constructor(name: string) {    this.name = name;  }  increment(): void { this.count++; }  get value(): number { return this.count; }  // c.value  static create(): Counter { return new Counter("x"); }}const c = new Counter("kliky");

Dědičnost a interface

class Dog extends Animal {  speak(): string { return "haf"; }}class ArrayStack<T> implements Stack<T> {  private items: T[] = [];  // … metody z interface Stack}

Zásobník (stack)

const stack: number[] = [];stack.push(1);        // vložitstack.pop();          // vyndat poslednístack.at(-1);         // vrchol (bez vyndání)stack.length === 0;   // prázdný?

Fronta (queue)

const queue: number[] = [start];let head = 0;while (head < queue.length) {  const x = queue[head++];   // místo pomalého shift()  // … queue.push(soused)}

ListNode (jako na LeetCode)

class ListNode {  val: number;  next: ListNode | null;  constructor(val?: number, next?: ListNode | null) {    this.val = val ?? 0;    this.next = next ?? null;  }}for (let n = head; n !== null; n = n.next) {  console.log(n.val);}

Dummy uzel a dva ukazatele

const dummy = new ListNode(0, head);let tail = dummy;// … tail.next = uzel; tail = tail.next;return dummy.next; let slow = head, fast = head;   // prostředek seznamuwhile (fast && fast.next) {  slow = slow!.next;  fast = fast.next.next;}

TreeNode a DFS

class TreeNode {  val: number;  left: TreeNode | null;  right: TreeNode | null;  constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {    this.val = val ?? 0;    this.left = left ?? null;    this.right = right ?? null;  }}function depth(node: TreeNode | null): number {  if (!node) return 0;  return 1 + Math.max(depth(node.left), depth(node.right));}

BFS po úrovních

let level: TreeNode[] = root ? [root] : [];while (level.length > 0) {  const next: TreeNode[] = [];  for (const node of level) {    if (node.left) next.push(node.left);    if (node.right) next.push(node.right);  }  level = next;}
8

Čísla a Math

Lekce 8

Zaokrouhlování

Math.floor(7 / 2);   // 3   celočíselné děleníMath.trunc(-3.5);    // -3  useknutí k nuleMath.floor(-3.5);    // -4  vždy dolůMath.ceil(2.1);      // 3Math.round(2.5);     // 3

Math

Math.abs(-5);         // 5Math.max(a, b, c);Math.min(a, b);Math.sqrt(16);        // 42 ** 10;              // 1024Math.log2(8);         // 37 % 3;                // 1 (zbytek)((-7 % 3) + 3) % 3;   // 2 – kladné modulo

Limity a obří čísla

Infinity; -Infinity;       // start pro min / maxNumber.MAX_SAFE_INTEGER;   // 2⁵³ − 1const MOD = 1_000_000_007;const big = 2n ** 64n;     // BigIntNumber(big % 7n);          // zpět na number

Násobení dvou čísel kolem 10⁹ už ztrácí přesnost – na (a * b) % MOD použij BigInt.

Bitové operace

x & 1;         // 1 = lichéx >> 1;        // celočíselně / 21 << k;        // 2^ka ^ b;         // XOR – stejné se vyrušíx & (x - 1);   // smaže nejnižší jedničku

Bitové operace pracují s 32bitovými čísly.

Kontroly čísel

Number.isInteger(5);     // trueNumber.isNaN(0 / 0);     // trueNumber.isFinite(1 / 0);  // false

PastMath.max(...obříPole)

Math.max(...hugeArray);   // ❌ spadne (moc argumentů)let best = -Infinity;     // ✅for (const v of hugeArray) best = Math.max(best, v);
9

Vzory na LeetCode

Lekce 8

Two pointers

let l = 0;let r = a.length - 1;while (l < r) {  const sum = a[l] + a[r];  if (sum === target) return [l, r];  if (sum < target) l++;  else r--;}

Seřazená pole a palindromy. O(n).

Sliding window

const seen = new Set<string>();let left = 0;let best = 0;for (let right = 0; right < s.length; right++) {  while (seen.has(s[right])) seen.delete(s[left++]);  seen.add(s[right]);  best = Math.max(best, right - left + 1);}

Souvislé úseky pole nebo stringu: pravý okraj roztahuj, levý stahuj. O(n).

Prefix sum

const pre = [0];for (const x of a) pre.push(pre[pre.length - 1] + x);// součet a[i..j] (včetně j) v O(1):const sum = pre[j + 1] - pre[i];

Binary search

let lo = 0;let hi = a.length - 1;while (lo <= hi) {  const mid = (lo + hi) >> 1;  if (a[mid] === target) return mid;  if (a[mid] < target) lo = mid + 1;  else hi = mid - 1;}return -1;

Monotónní stack

// za kolik dní bude tepleji? (LeetCode 739)const res = new Array<number>(t.length).fill(0);const stack: number[] = [];   // indexyfor (let i = 0; i < t.length; i++) {  while (stack.length && t[stack.at(-1)!] < t[i]) {    const j = stack.pop()!;    res[j] = i - j;  }  stack.push(i);}

„Nejbližší větší / menší prvek“ v O(n).

BFS na mřížce

const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]];const queue: [number, number][] = [[sr, sc]];const seen = new Set<string>([`${sr},${sc}`]);for (let h = 0; h < queue.length; h++) {  const [r, c] = queue[h];  for (const [dr, dc] of dirs) {    const nr = r + dr, nc = c + dc;    if (nr < 0 || nc < 0 || nr >= rows || nc >= cols) continue;    const key = `${nr},${nc}`;    if (seen.has(key)) continue;    seen.add(key);    queue.push([nr, nc]);  }}

Dynamické programování

// kolika způsoby vyjdeš n schodů po 1 nebo 2const dp = new Array<number>(n + 1).fill(0);dp[0] = 1;for (let i = 1; i <= n; i++) {  dp[i] = dp[i - 1] + (i >= 2 ? dp[i - 2] : 0);}// 2D tabulka (m + 1) × (n + 1):const t = Array.from({ length: m + 1 }, () => new Array<number>(n + 1).fill(0));

Backtracking

const res: number[][] = [];const path: number[] = [];function bt(start: number): void {  res.push([...path]);          // ulož kopii!  for (let i = start; i < nums.length; i++) {    path.push(nums[i]);    bt(i + 1);    path.pop();                 // vrať krok zpět  }}bt(0);   // všechny podmnožiny

Vlastní min-halda

class MinHeap {  private h: number[] = [];  get size(): number { return this.h.length; }  peek(): number | undefined { return this.h[0]; }  push(x: number): void {    const h = this.h;    h.push(x);    let i = h.length - 1;    while (i > 0) {      const p = (i - 1) >> 1;      if (h[p] <= h[i]) break;      [h[p], h[i]] = [h[i], h[p]];      i = p;    }  }  pop(): number | undefined {    const h = this.h;    if (h.length === 0) return undefined;    const top = h[0];    const last = h.pop()!;    if (h.length > 0) {      h[0] = last;      let i = 0;      while (true) {        const l = 2 * i + 1, r = l + 1;        let m = i;        if (l < h.length && h[l] < h[m]) m = l;        if (r < h.length && h[r] < h[m]) m = r;        if (m === i) break;        [h[m], h[i]] = [h[i], h[m]];        i = m;      }    }    return top;  }}

JavaScript haldu nemá. Pro max-haldu vkládej -x. Na LeetCode je k dispozici i knihovna @datastructures-js/priority-queue.

10

Složitost

Lekce 8

Jak rychlé jsou operace

OperaceSložitost
arr[i], push, pop, lengthO(1)
shift, unshift, spliceO(n)
includes, indexOf, findO(n)
slice, [...arr], map, filterO(n)
sortO(n log n)
Map / Set: get, set, has, deleteO(1) v průměru
s.slice, s.split, s + tO(n)
binární vyhledáváníO(log n)

Jaké řešení stačí podle n

Velikost vstupuStačí algoritmus
n ≤ 12O(n!) – všechny permutace
n ≤ 25O(2ⁿ) – podmnožiny, backtracking
n ≤ 500O(n³)
n ≤ 5 000O(n²)
n ≤ 10⁶O(n log n) nebo O(n)
n ≤ 10⁹O(log n) nebo O(1)

Z omezení v zadání (např. „1 ≤ n ≤ 10⁵“) poznáš, jak rychlé řešení potřebuješ. Počítej zhruba se 10⁸ operacemi za sekundu.