1. What algorithms are better? πŸ‘©β€

μ½”λ“œλ₯Ό μž‘μ„±ν•˜κ³ , μ•Œκ³ λ¦¬μ¦˜μ„ κ΅¬ν˜„ν•  λ•Œ μ€‘μš”ν•˜κ²Œ 생각해야 ν•˜λŠ” 것은 λ‹€μŒκ³Ό κ°™λ‹€.

  • μ–Όλ§ˆλ‚˜ λΉ λ₯Έκ°€?
  • μ–Όλ§ˆμž 적은 λ©”λͺ¨λ¦¬λ₯Ό μ‚¬μš©ν•˜λŠ”κ°€?
  • μ–Όλ§ˆλ‚˜ 읽기 μ‰¬μš΄κ°€?

2. How faster? πŸ‘©β€

μ•Œκ³ λ¦¬μ¦˜μ„ κ΅¬ν˜„ν•˜λ©° μ–Όλ§ˆλ‚˜ λΉ λ₯Έκ°€λ₯Ό μΈ‘μ •ν•˜λ €λ©΄ λ¬Έμ„œκ°€ μ—΄λ¦° μ‹œκ°„μœΌλ‘œλΆ€ν„° κ°€λ™λ˜λŠ” 타이머 ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

function addUpTo(n) {
  let total = 0;
  for (let i = 1; i <= n; i++) {
    total += i;
  }
  return total;
}

let t1 = performance.now();
addUpTo(1000000000);
let t2 = performance.now();
console.log(`Time Elapsed: ${(t2 - t1) / 1000} seconds.`)

μΈ‘μ •ν•˜κ³ μž ν•˜λŠ” μ½”λ“œμ˜ 전후에 performance.now() ν•¨μˆ˜λ‘œ μ‹œκ°„μ„ μΈ‘μ •ν•΄ 두 μ‹œκ°„μ°¨λ₯Ό κ΅¬ν•¨μœΌλ‘œμ¨ μ‹€ν–‰ μ‹œκ°„μ„ ꡬ할 수 μžˆλ‹€. ν•˜μ§€λ§Œ μ΄λŸ°μ‹μœΌλ‘œ μ½”λ“œμ˜ μ‹€ν–‰ μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” 것이 항상 쒋은 방법은 μ•„λ‹ˆλ‹€. μ—¬λŸ¬ 개의 맀우 λΉ λ₯Έ μ•Œκ³ λ¦¬μ¦˜ μ€‘μ—μ„œλ„ κ°€μž₯ λΉ λ₯Έ μ•Œκ³ λ¦¬μ¦˜μ΄ μ‘΄μž¬ν• ν…λ° λ„ˆλ¬΄ λΉ λ₯΄κ²Œ μ‹€ν–‰λ˜λŠ” 경우 편차둜 인해 μ •ν™•ν•œ κ²°κ³Όλ₯Ό μ–»κΈ° νž˜λ“€λ‹€. λ•Œλ‘œλŠ” λ„ˆλ¬΄ 였래 κ±Έλ¦¬λŠ” μ•Œκ³ λ¦¬μ¦˜μ΄μ–΄μ„œ μ‹€μ œ κ²°κ³Όλ₯Ό ν™•μΈν•˜λŠ” 데 λ„ˆλ¬΄ λ§Žμ€ μ‹œκ°„μ΄ μ†Œλͺ¨λ  수 μžˆλ‹€. λ˜ν•œ 이 방법은 μ»΄ν“¨ν„°μ˜ μ„±λŠ₯에 영ν–₯을 λ°›λŠ”λ‹€.

직접 μ‹œκ°„μ„ μΈ‘μ •ν•˜λŠ” 것 보닀 쒋은 방법은 컴퓨터가 μ²˜λ¦¬ν•΄μ•Όν•˜λŠ” μ—°μ‚° 개수λ₯Ό μ„ΈλŠ” 것이닀.

addUpTo 1

n 이 μ–Όλ§ˆλ‚˜ 큰 μˆ˜μ΄λ“  상관 없이 3 번의 연산이 λ°œμƒν•œλ‹€.

addUpTo 2

5n + 2 번의 연산이 λ°œμƒν•˜λ―€λ‘œ n 이 클수둝 μ—°μ‚° 횟수 λ˜ν•œ λŠ˜μ–΄λ‚œλ‹€.

μ΄λŸ¬ν•œ ν‘œν˜„ 방식을 Big O라 ν•œλ‹€.

3. Big O Definition πŸ‘©β€

1. Time Complexity

μ•Œκ³ λ¦¬μ¦˜μ΄ O(f(n))μ΄λΌλŠ” 것은 μ—°μ‚°ν•΄μ•Ό ν•  n이 증가함에 따라 μ΅œλŒ€ μ—°μ‚° 횟수 f(n)이 μ–Όλ§ˆλ‚˜ ν•„μš”ν•œμ§€λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

  • f(n) = n: linear
  • f(n) = nΒ²: quadratic
  • f(n) = 1: constant
function addUpTo(n) {
  return n * (n + 1) / 2;
}
function addUpTo(n) {
  let total = 0;
  for (let i = 1; i <= n; i++) {
    total += i;
  }
  return total;
}

μœ„ ν•¨μˆ˜λŠ” 항상 3번의 연산을 ν–ˆκ³ , μ•„λž˜ ν•¨μˆ˜λŠ” 5n + 2 번의 연산을 ν–ˆλ‹€. ν•˜μ§€λ§Œ λ‚΄λΆ€μ μœΌλ‘œ n λ²ˆμ΄λ“ , 5n λ²ˆμ΄λ“  n 이 컀지면 κ·Έλž˜ν”„λ₯Ό ν‘œν˜„ν•˜λŠ” 데 μžˆμ–΄ 이것은 크게 μ€‘μš”ν•˜μ§€ μ•Šλ‹€. μ€‘μš”ν•œ 것은 μ§€μˆ˜μ΄λ‹€. λ”°λΌμ„œ μœ„ ν•¨μˆ˜λŠ” O(1)으둜 ν‘œν˜„λ  수 있고, μ•„λž˜ ν•¨μˆ˜λŠ” O(n)으둜 ν‘œν˜„λ  수 μžˆλ‹€.

countUpAndDown

μœ„ ν•¨μˆ˜μ˜ 경우, O(n)번의 연산이 2번 μžˆμœΌλ―€λ‘œ Big O κ°€ O(2n)이라 생각할 수 μžˆμœΌλ‚˜, λ‚΄λΆ€ 연산이 n λ²ˆμ΄λ“ , 5n λ²ˆμ΄λ“  μ‚¬μ†Œν•œ 것은 λ¬΄μ‹œν•œ 채 κ·Έλž˜ν”„μ˜ 큰 그림만 보기둜 ν–ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ 이것은 μ—¬μ „νžˆ O(n)이닀.

μ™œ λ¬΄μ‹œν• κΉŒ? 1μ°¨ 방정식이 f(n) = n 이든, f(n) = 2n 이든, f(n) = 100n 이든 2차방정식과 λΉ„κ΅ν•˜λ©΄ κ²°κ΅­ κΈ°μšΈκΈ°λŠ” 크게 μ€‘μš”ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ΄λ‹€. 1μ°¨ 방정식 f(n) = 10000n이 λ˜μ–΄λ΄€μž 2μ°¨ 방정식 f(n) = n²에 λΉ„ν•˜λ©΄ μ§€μˆ˜ μžμ²΄κ°€ 달라지기 λ•Œλ¬Έμ΄λ‹€. λ”°λΌμ„œ 이 경우, μ•žμ— μ–΄λ–€ 기울기 μƒμˆ˜κ°’μ΄ λΆ™μ—ˆλŠ”μ§€λŠ” μ „ν˜€ μ€‘μš”ν•˜μ§€ μ•Šλ‹€.


printAllPairs

μœ„ ν•¨μˆ˜μ˜ κ²½μš°λŠ” λ‚΄λΆ€ μ—°μ‚° 횟수λ₯Ό λ¬΄μ‹œν•˜μ§€ μ•ŠλŠ”λ‹€. O(n)의 μ—°μ‚° μ•ˆμ— O(n)의 연산이 μ€‘μ²©λ˜μ–΄ 있기 λ•Œλ¬Έμ΄λ‹€. μ•žμ—μ„œ 이야기 ν–ˆλ“―μ΄ 1μ°¨ λ°©μ •μ‹μ—μ„œ 2μ°¨ λ°©μ •μ‹μœΌλ‘œ λ„˜μ–΄κ°€λŠ” 것이닀. 이것은 O(n * n)이 λ˜μ–΄ O(nΒ²)이 λœλ‹€.

μ‰½κ²Œ 말해, μƒμˆ˜λŠ” λ¬΄μ‹œν•œ 채 ν‘œν˜„ν•œλ‹€κ³  μƒκ°ν•˜λ©΄ λœλ‹€.

  • O(232n + 10)은 μƒμˆ˜κ°’μ„ λ¬΄μ‹œν•œ 채 O(n)으둜 ν‘œκΈ°ν•œλ‹€.
  • O(500000000)은 μƒμˆ˜κ°’μ„ λ¬΄μ‹œν•œ 채 O(1)으둜 ν‘œκΈ°ν•œλ‹€.
  • O(13nΒ² + 13)은 μƒμˆ˜κ°’μ„ λ¬΄μ‹œν•œ 채 O(nΒ²)으둜 ν‘œκΈ°ν•œλ‹€.
  • O(nΒ² + 500n)은 μƒμˆ˜κ°’μ„ λ¬΄μ‹œν•œ 채 O(nΒ²)으둜 ν‘œκΈ°ν•œλ‹€.

μ‚¬μ†Œν•œ 연산을 λ¬΄μ‹œν•˜λŠ” μ΄μœ λŠ” 컴퓨터가 2 + 2λ₯Ό μ²˜λ¦¬ν•˜λŠ” μ‹œκ°„κ³Ό 100만 + 2λ₯Ό μ²˜λ¦¬ν•˜λŠ” μ‹œκ°„μ€ λΉ„μŠ·ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.


JavaScript μ—μ„œ Time Complexity λ₯Ό 이야기 ν•  λ•Œ κ·œμΉ™μ΄ μžˆλ‹€.

  1. μ‚°μˆ  연산은 constantλ‹€.
  2. λ³€μˆ˜ 할당은 constantλ‹€.
  3. array 에 index 둜 μ ‘κ·Όν•˜κ±°λ‚˜ object 에 key 둜 μ ‘κ·Όν•˜λŠ” 것은 constantλ‹€.
  4. loop μ•ˆμ— μ–΄λ–€ 연산이 μ‘΄μž¬ν•˜λ“ , loop 의 길이만큼 μ—°μ‚°ν•œλ‹€(쀑첩 loop λ₯Ό 이야기 ν•˜λŠ” 것이 μ•„λ‹ˆλ‹€).

loop 의 쀑첩이 2회인 κ²ƒλ§Œ 해도 μ—„μ²­λ‚œ 연산을 μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— loop 쀑첩을 3νšŒμ”© ν•˜λŠ” μ½”λ“œλŠ” μž‘μ„±ν•˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— λŒ€λΆ€λΆ„μ˜ μΆ”μ„ΈλŠ” λ‹€μŒκ³Ό 같이 ν‘œν˜„λœλ‹€.

Big O Graphs


Examples

function logAtLeast5(n) {
  for (var i = 1; i <= Math.max(5, n); i++) {
    console.log(i);
  }
}

μ‰½κ²Œ μ˜ˆμƒν•  수 μžˆλ“―μ΄ O(n)이닀.

function logAtMost5(n) {
  for (var i = 1; i <= Math.min(5, n); i++) {
    console.log(i);
  }
}

이 κ²½μš°λ„ O(n)이라 생각할 수 μžˆμœΌλ‚˜, 이 ν•¨μˆ˜λŠ” n 이 컀져도 μ•„λ¬΄λŸ° 영ν–₯을 λ―ΈμΉ˜μ§€ λͺ»ν•œλ‹€. n 이 아무리 컀져도 μ΅œλŒ€ 5λ²ˆμ΄λ‹€. λ”°λΌμ„œ O(1)이닀.

2. Space Complexity

Time Complexity κ°€ μ•Œκ³ λ¦¬μ¦˜μ˜ μ†Œμš” μ‹œκ°„μ„ λ‹€λ£¨μ—ˆλ‹€λ©΄, Space Complexity, 곡간 λ³΅μž‘λ„λž€ μ•Œκ³ λ¦¬μ¦˜μ˜ λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ„ 닀룬닀.

기본적으둜, μž…λ ₯κ°’ n 이 컀질수둝, ν•„μš”λ‘œ ν•˜λŠ” 곡간이 λ¬΄ν•œλŒ€λ‘œ λŠ˜μ–΄λ‚œλ‹€. ν•˜μ§€λ§Œ μ—¬κΈ°μ„œ μ΄μ•ΌκΈ°ν•˜λŠ” λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰μ€ μž…λ ₯λ˜λŠ” 것은 μ œμ™Έν•˜κ³  μ•Œκ³ λ¦¬μ¦˜ μžμ²΄κ°€ ν•„μš”λ‘œ ν•˜λŠ” 곡간(λ©”λͺ¨λ¦¬ μ‚¬μš©λŸ‰)을 μ˜λ―Έν•œλ‹€.


JavaScript μ—μ„œ Space Complexity λ₯Ό 이야기 ν•  λ•Œ κ·œμΉ™μ΄ μžˆλ‹€.

  • λŒ€λΆ€λΆ„μ˜ boolean, number, undefined, null 은 constant spaceλ‹€.
  • String 은 λ¬Έμžμ—΄μ˜ 길이만큼 O(n)의 곡간을 μ°¨μ§€ν•œλ‹€.
  • Reference Types(array, object)λŠ” λ°°μ—΄μ˜ 길이, key 의 개수만큼 O(n)의 곡간을 μ°¨μ§€ν•œλ‹€.


sum

number 2κ°œμ΄λ―€λ‘œ 1 + 1이닀. λ‘˜λ‹€ constant μ΄λ―€λ‘œ O(1)이 λœλ‹€.

double

array κ°€ 길이만큼 λŠ˜μ–΄λ‚˜λ―€λ‘œ, O(n)이 λœλ‹€.

3. log complexity

f(n) = nΒ² + 8n + 24λŠ” nΒ² + 8n + 24 = 0이 λ˜λŠ” 이차 λ°©μ •μ‹μ˜ ν•΄λ₯Ό κ΅¬ν•˜λŠ” κ²ƒμœΌλ‘œ, 이 μΌ€μ΄μŠ€μ˜ complexity λŠ” f(n) = nΒ²μ˜€λ‹€.

μš°λ¦¬λŠ” μ–΄λ–€ κ°’μ˜ λ²”μœ„κ°€ 맀우 ν¬κ±°λ‚˜ linear ν•˜μ§€ μ•Šκ³  배수둜써 μ¦κ°€ν•˜κ±°λ‚˜ κ°μ†Œν•˜λŠ” 경우(i.e. 진도, μ‹ν’ˆμ˜ λΆ€νŒ¨ μ§€μˆ˜, μ€ν–‰μ˜ 볡리) 둜그λ₯Ό μ·¨ν•΄ λ‹¨μˆœν™” μ‹œν‚¨λ‹€. μ»΄ν“¨ν„°μ—μ„œ 이것이 μ€‘μš”ν•œ μ΄μœ λŠ” μ–΄λ–€ 탐색 μ•Œκ³ λ¦¬μ¦˜λ“€ μ—­μ‹œ 탐색 ν•΄μ•Ό ν•  λŒ€μƒμ˜ λ²”μœ„κ°€ 맀우 컀 log λ₯Ό μ‚¬μš©ν•œ μˆ˜μ‹μœΌλ‘œ λ³΅μž‘λ„κ°€ ν‘œν˜„λ˜λŠ” κ²½μš°κ°€ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

λ‹Ήμ—°νžˆ μ§€μˆ˜ν•¨μˆ˜μ™€ λ§ˆμ°¬κ°€μ§€λ‘œ λ‘œκ·Έν•¨μˆ˜λ„ κ·Έλž˜ν”„ 좔세에 큰 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠλŠ” μ‚¬μ†Œν•œ 것듀은 λ¬΄μ‹œν•˜κ³  ν‘œν˜„μ„ ν•œλ‹€. 예λ₯Ό λ“€μ–΄ log(nΒ² + 500n + 2000)이라 ν•˜λ”λΌλ„ κ·Έλž˜ν”„ 좔세에 영ν–₯을 λ―ΈμΉ˜λŠ” log(nΒ²)만 보기둜 ν•˜λŠ” 것이닀.

4개의 둜그 방정식 log2n, log3n, log2n10, log2n100 을 예둜 λ“€μ–΄λ³΄μž. 기울기λ₯Ό 비ꡐ해보면 log3n < log2n < 10log2n < 100log2n κ°€ λœλ‹€.

μ—¬κΈ°μ„œ 핡심은 0 < log3n < nλΌλŠ” 것이닀. λ§ˆμ°¬κ°€μ§€λ‘œ 0 < log2n < n, n < 10log2n < nΒ², n < 100log2n < nΒ² 관계가 μ„±λ¦½λœλ‹€.

즉, 밑이 μ–Όλ§ˆμΈμ§€, μ•žμ— κ³±ν•΄μ§€λŠ” μˆ˜κ°€ μ–Όλ§ˆμΈμ§€λŠ” 크게 μ€‘μš”ν•˜μ§€ μ•Šλ‹€. μ•žμ΄ μžˆλƒ 없냐가 μ€‘μš”ν•œ 것이닀. λ”°λΌμ„œ, log n λ˜λŠ” nlog n두 μΌ€μ΄μŠ€λ‘œ ν‘œν˜„ν•  수 μžˆλ‹€.

μ΄λ“€μ˜ κΈ°μšΈκΈ°μ— λ”°λ₯Έ κ·Έλž˜ν”„ μΆ”μ„Έ 관계λ₯Ό ν‘œν˜„ν•˜λ©΄, O(log n)은 O(1)κ³Ό O(n) 사이에 μœ„μΉ˜ν•˜κ³ , O(nlog n)은 O(n)κ³Ό O(nΒ²) 사이에 μœ„μΉ˜ν•˜κ²Œ λœλ‹€.

Big O Graphs

κ·Έλž˜μ„œ μœ„μ™€ 같은 κ·Έλž˜ν”„κ°€ λ‚˜μ˜€κ²Œ λ˜λŠ” 것이닀.


4. Object and Array πŸ‘©β€

1. Object

일반적으둜 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ Key-Value Types 의 νŠΉμ§•μ€ Hash Tables λ₯Ό 기반으둜 ν•˜κΈ° λ•Œλ¬Έμ— 기본적으둜 Unordered Collection이며, λΉ λ₯Έ μ†λ„μ˜ access, insertion, removal 에 μ ν•©ν•œ 데이터 νƒ€μž…μ΄λ‹€. λ”°λΌμ„œ 일반적으둜 λ‹€μŒκ³Ό 같은 νŠΉμ„±μ„ κ°–λŠ”λ‹€.

  • Access: O(1)
  • Insertion: O(1)
  • Removal: O(1)
  • Searching: O(N)

λ”°λΌμ„œ μ£Όμš” λ©”μ„œλ“œμ˜ Time Complexity λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

  • Object.keys: O(N)
  • Object.values: O(N)
  • Object.entries: O(N)
  • hasOwnProperty: O(1)
Object.keys(instructor)                // O(N) 
instructor.hasOwnProperty('firstName')  // O(1)

λ¬Όλ‘ , μ–Έμ–΄λ§ˆλ‹€ LinkedHashMapκ³Ό 같은 Ordered Collection의 κ΅¬ν˜„μ΄ λ˜μ–΄μžˆκ±°λ‚˜ κ΅¬ν˜„μ„ ν•΄ μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€.

2. Arrays

일반적으둜 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ Array Types 의 νŠΉμ§•μ€ Index λ₯Ό 기반으둜 ν•˜κΈ° λ•Œλ¬Έμ— 기본적으둜 Ordered Collection이며, μ •λ ¬λœ 데이터에 μ ν•©ν•œ 데이터 νƒ€μž…μœΌλ‘œ λΉ λ₯Έ access 속도λ₯Ό κ°–λŠ”λ‹€. ν•˜μ§€λ§Œ μ •λ ¬λ˜μ–΄μ•Ό ν•˜κΈ° λ•Œλ¬Έμ— insertion, removal 은 μΌ€μ΄μŠ€μ— 따라 달라진닀.

  • Access: O(1)
  • Insertion: It depends…
  • Removal: It depends…
  • Searching: O(N)

λ”°λΌμ„œ μ£Όμš” λ©”μ„œλ“œμ˜ Time Complexity λŠ” λ‹€μŒκ³Ό κ°™λ‹€.

  • push: O(1)
  • pop: O(1)
  • unshift: O(N)
  • shift: O(N)
  • splice: O(N)
  • concat: O(N)
  • slice: O(N)
  • reverse: O(N)
  • forEach/map/filter/reduce/etc.: O(N)
  • sort: O(NlogN)

λ¬Όλ‘ , μ–Έμ–΄λ§ˆλ‹€ Setκ³Ό 같은 Unordered Collection의 κ΅¬ν˜„μ΄ λ˜μ–΄μžˆκ±°λ‚˜ κ΅¬ν˜„μ„ ν•΄ μ‚¬μš©ν•  μˆ˜λ„ 있고, 배열보닀 Single Linked Listλ‚˜ Double Linked List와 같은 데이터 νƒ€μž…μ΄ 더 λΉ λ₯Ό μˆ˜λ„ μžˆλ‹€.




Reference

  1. Colt Steele, β€œJavaScript μ•Œκ³ λ¦¬μ¦˜ & 자료ꡬ쑰 λ§ˆμŠ€ν„°ν΄λž˜μŠ€β€ Udemy.com. last modified Aug. 2023, https://www.udemy.com/course/best-javascript-data-structures.