--- id: cs-big-o-practical title: Big-O 실전 — 실제 성능 / 측정 / 함정 category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [cs, algorithm, big-o, vibe-coding] tech_stack: { language: "TS", applicable_to: ["Backend", "Frontend"] } applied_in: [] aliases: [Big O, time complexity, space complexity, amortized, hidden constant] --- # Big-O 실전 > Big-O 가 알고리즘의 핵심 지표. **그러나 hidden constant + cache locality + 입력 크기 도 중요**. O(N) 가 O(log N) 보다 느릴 수 있다 (작은 N). ## 📖 핵심 개념 - O(1): 상수. - O(log N): 이진 검색. - O(N): linear scan. - O(N log N): merge sort, sort. - O(N²): nested loop. - O(2^N), O(N!): 거의 사용 X (작은 N). ## 💻 코드 패턴 ### 자주 쓰는 자료구조 복잡도 ``` Array (JS): push/pop: O(1) amortized shift/unshift: O(N) — 큰 시작 element 이동 index access: O(1) indexOf: O(N) Map / Set (V8): get/set/has: O(1) average (hash collision 시 worst O(N)) iteration: insertion order Object: property access: O(1) average LinkedList: prepend/append: O(1) index access: O(N) Heap (priority queue): insert/pop: O(log N) Binary search: on sorted array: O(log N) Sort: Array.sort: O(N log N) (TimSort in V8) ``` ### Common 변환 ```ts // O(N²) — nested for (const x of arr) { for (const y of arr) { if (x.id === y.parent) ...; } } // O(N) with Map const byId = new Map(arr.map(x => [x.id, x])); for (const x of arr) { const parent = byId.get(x.parent); if (parent) ...; } ``` ```ts // O(N²) — array.includes for (const x of arr) { if (otherArr.includes(x.id)) ...; // O(M) per loop } // O(N+M) const set = new Set(otherArr); for (const x of arr) { if (set.has(x.id)) ...; // O(1) } ``` ### Hidden constant ``` O(log N) binary search: - ~20 comparison for 1M items - 매 comparison = 비교 + index calc O(N) linear with simd: - 1M cmp = 100ns 같은 cache friendly → 작은 N (<100) = 상수 차이 큼. N = 100K → log N (17) vs N = 차이 명확. ``` ### Cache locality ```ts // ✅ Sequential access — cache 친화 for (let i = 0; i < arr.length; i++) sum += arr[i]; // ❌ Random — cache miss for (const i of shuffled) sum += arr[i]; // → 5-20x 느림 ``` ### Amortized ```ts // Array.push: 보통 O(1). // 가끔 capacity 확장 → 모두 copy = O(N). // 평균 O(1) (amortized). // Hash map resize: 같은 원리. ``` ### 작은 vs 큰 N ``` N = 10: O(N²) = 100, OK. N = 1000: O(N²) = 1M, 느려질 수 있음. N = 1M: O(N²) = 10^12, 절대 X. O(N log N). N = 1G: O(N) 도 비쌈. 분산. ``` → 입력 크기 모르면 안전하게 좋은 알고리즘. ### 측정 ```ts const t = performance.now(); const result = myFunction(input); console.log('took', performance.now() - t, 'ms'); // 더 정확 const COUNT = 10000; let total = 0; for (let i = 0; i < COUNT; i++) { const t = performance.now(); myFunction(input); total += performance.now() - t; } console.log('avg', total / COUNT, 'ms'); ``` ### Common O(N log N) ```ts // Sort arr.sort((a, b) => a.value - b.value); // 그 후 binary search function find(target: number): number | undefined { let lo = 0, hi = arr.length - 1; while (lo <= hi) { const mid = (lo + hi) >> 1; if (arr[mid].value === target) return arr[mid]; if (arr[mid].value < target) lo = mid + 1; else hi = mid - 1; } } ``` → Sort 한 번 + N 검색 = O(N log N). N 검색 X = O(N²). ### Top-K (heap) ```ts import Heap from 'heap-js'; function topK(arr: number[], k: number): number[] { const minHeap = new Heap(); for (const x of arr) { minHeap.push(x); if (minHeap.size() > k) minHeap.pop(); // 가장 작은 제거 } return minHeap.toArray(); // top K } // O(N log K) — N log N (sort) 보다 빠름. ``` ### Sliding window ```ts // 합 N 길이 array 의 K 길이 sub 의 max function maxSumWindow(arr: number[], k: number): number { let sum = 0; for (let i = 0; i < k; i++) sum += arr[i]; let max = sum; for (let i = k; i < arr.length; i++) { sum += arr[i] - arr[i - k]; // O(1) update max = Math.max(max, sum); } return max; } // O(N) — 매번 sum 다시 X. ``` ### Two pointer ```ts // Sorted array — sum = target? function twoSum(arr: number[], target: number): [number, number] | null { let lo = 0, hi = arr.length - 1; while (lo < hi) { const sum = arr[lo] + arr[hi]; if (sum === target) return [lo, hi]; if (sum < target) lo++; else hi--; } return null; } // O(N). ``` ### Dynamic programming ```ts // Fibonacci O(2^N) → O(N) memo const memo = new Map(); 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; } ``` ### Graph ```ts // BFS — O(V + E) function bfs(start: Node) { const visited = new Set(); const queue = [start]; while (queue.length > 0) { const node = queue.shift()!; // ❌ O(N) shift // 또는 더 나은 = deque 또는 index if (visited.has(node)) continue; visited.add(node); queue.push(...node.neighbors); } } ``` → Array shift 가 O(N). 큰 BFS = deque library. ### When to optimize ``` 1. Profile first — hot path 만. 2. Big-O 가 일반 답. 3. Cache / locality 가 micro-opt. 4. Algorithm > implementation. "Premature optimization is the root of all evil." (Knuth) But: O(N²) → O(N) 는 premature 가 아님. ``` ### V8 (JavaScript) 특이 ``` .shift() / .unshift(): O(N). .push() / .pop(): O(1) amortized. Object property access: - 같은 shape: O(1) - 다른 shape mix: 느림 (위 V8 문서) ``` ### Memory complexity ```ts // O(N²) memory const matrix: number[][] = []; for (let i = 0; i < N; i++) { matrix[i] = []; for (let j = 0; j < N; j++) matrix[i][j] = ...; } // 큰 N (10K+) = OOM 가능. ``` ### Algorithm 선택 cheat sheet ``` Search: Sorted: binary search O(log N) Unsorted: linear O(N) 또는 hash set O(1) Sort: General: TimSort (V8) O(N log N) Small (<10): insertion O(N²) but 빠름 Distinct integers: counting / radix O(N) Top-K: K << N: heap O(N log K) K close to N: sort O(N log N) Group: reduce / Map O(N) Distinct: Set O(N) Combinations: backtracking O(2^N) — 작은 N 만. ``` ## 🤔 의사결정 기준 | 입력 크기 | 알고리즘 | |---|---| | <100 | 어떤 거나 OK | | <10K | O(N²) 일부 가능 | | <1M | O(N log N) 안정 | | <1B | O(N) 또는 분산 | | 1B+ | 분산 + sampling | ## ❌ 안티패턴 - **`Array.includes` in loop**: O(N²). Set / Map. - **`arr.shift()` 반복**: O(N²). Index 또는 deque. - **모든 곳 micro-opt**: 가독성 잃음. - **Big-O 무시 + V8 trick**: 알고리즘 우선. - **Sort 매번**: cache. - **Recursion + 작은 N — overhead 가 cost**: iterative. - **JSON.parse 큰 string**: O(N) but 큰 constant. stream parser. ## 🤖 LLM 활용 힌트 - Big-O 우선 — 그 후 micro. - Set / Map = 80% 개선의 답. - Profile → hot path. ## 🔗 관련 문서 - [[Perf_V8_Optimization]] - [[CS_Bloom_Filter]] - [[CS_Probabilistic_Data_Structures]]