- Published on
π JavaScript μμλλ©΄ μ μ©ν νμ μκ³ λ¦¬μ¦
1. μν κ΄λ ¨ μκ³ λ¦¬μ¦
1.1 μ΅λ곡μ½μ (GCD) - μ ν΄λ¦¬λ νΈμ λ²
μκ° λ³΅μ‘λ: O(log min(a, b))
// β
μ¬κ· λ²μ (κ°μ₯ κ°κ²°)
function gcd(a, b) {
return b === 0 ? a : gcd(b, a % b)
}
// β
λ°λ³΅ λ²μ (μ€ν μ€λ²νλ‘μ° λ°©μ§)
function gcd(a, b) {
while (b !== 0) {
;[a, b] = [b, a % b]
}
return a
}
// μ€μ μμ: λ μμ μ΅λ곡μ½μ
gcd(48, 18) // 6
// μ€μ μμ: μ¬λ¬ μμ μ΅λ곡μ½μ
function gcdArray(arr) {
return arr.reduce((a, b) => gcd(a, b))
}
// μ€μ μμ: λΆμ κΈ°μ½λΆμ λ§λ€κΈ°
function simplifyFraction(numerator, denominator) {
const g = gcd(numerator, denominator)
return [numerator / g, denominator / g]
}
μ£Όμμ :
- μμ μ
λ ₯ μ μ λκ°μ μ·¨ν΄μΌ ν©λλ€:
gcd(Math.abs(a), Math.abs(b)) aμbμ€ νλκ° 0μ΄λ©΄ λ€λ₯Έ νλκ° μ΅λ곡μ½μμ λλ€.
1.2 μ΅μ곡배μ (LCM)
μκ° λ³΅μ‘λ: O(log min(a, b))
// β
GCDλ₯Ό μ΄μ©ν LCM κ³μ°
function lcm(a, b) {
return (a * b) / gcd(a, b)
}
// μ€μ μμ: λ μμ μ΅μ곡배μ
lcm(12, 18) // 36
// μ€μ μμ: μ¬λ¬ μμ μ΅μ곡배μ
function lcmArray(arr) {
return arr.reduce((a, b) => lcm(a, b))
}
// μ€μ μμ: μ£ΌκΈ° μ°ΎκΈ°
function findCommonPeriod(period1, period2) {
return lcm(period1, period2)
}
μ£Όμμ :
- ν° μμ κ³±μ
μ μ€λ²νλ‘μ°λ₯Ό λ°©μ§νλ €λ©΄:
(a / gcd(a, b)) * b - BigIntκ° νμν κ²½μ°:
(BigInt(a) * BigInt(b)) / BigInt(gcd(a, b))
1.3 μμ νλ³
μκ° λ³΅μ‘λ: O(βn)
// β
κΈ°λ³Έ μμ νλ³
function isPrime(n) {
if (n < 2) return false
if (n === 2) return true
if (n % 2 === 0) return false
for (let i = 3; i * i <= n; i += 2) {
if (n % i === 0) return false
}
return true
}
// μ€μ μμ: μμ 체ν¬
isPrime(17) // true
isPrime(15) // false
μ£Όμμ :
- 2λ μ μΌν μ§μ μμμ΄λ―λ‘ λ³λ μ²λ¦¬ν©λλ€.
i * i <= n쑰건μΌλ‘ βnκΉμ§λ§ νμΈν©λλ€.
1.4 μλΌν μ€ν λ€μ€μ 체
μκ° λ³΅μ‘λ: O(n log log n)
// β
μλΌν μ€ν
λ€μ€μ 체
function sieveOfEratosthenes(n) {
const isPrime = Array(n + 1).fill(true)
isPrime[0] = isPrime[1] = false
for (let i = 2; i * i <= n; i++) {
if (isPrime[i]) {
for (let j = i * i; j <= n; j += i) {
isPrime[j] = false
}
}
}
return isPrime
}
// μ€μ μμ: n μ΄νμ λͺ¨λ μμ λ°ν
function getPrimes(n) {
const isPrime = sieveOfEratosthenes(n)
return isPrime.map((prime, i) => (prime ? i : null)).filter((x) => x !== null)
}
// μ€μ μμ: μμ κ°μ μΈκΈ°
function countPrimes(n) {
const isPrime = sieveOfEratosthenes(n)
return isPrime.filter((x) => x).length
}
// μ€μ μμ: μμΈμλΆν΄
function primeFactors(n) {
const isPrime = sieveOfEratosthenes(n)
const factors = []
for (let i = 2; i * i <= n; i++) {
if (isPrime[i] && n % i === 0) {
while (n % i === 0) {
factors.push(i)
n /= i
}
}
}
if (n > 1) factors.push(n)
return factors
}
μ£Όμμ :
i * i <= nκΉμ§λ§ νμΈνλ©΄ μΆ©λΆν©λλ€.jλi * iλΆν° μμνμ¬ μ€λ³΅ 체ν¬λ₯Ό λ°©μ§ν©λλ€.
1.5 λ±μ°¨μμ΄ (Arithmetic Sequence)
λ±μ°¨μμ΄μ μ°μνλ λ νμ μ°¨μ΄κ° μΌμ ν μμ΄μ λλ€. 첫 λ²μ§Έ νμ , 곡차(common difference)λ₯Ό λΌκ³ ν λ:
- μΌλ°ν:
- ν© κ³΅μ:
ν© κ³΅μμ 첫 νκ³Ό λ§μ§λ§ νμ νκ· μ νμ κ°μλ₯Ό κ³±ν κ²κ³Ό κ°μ΅λλ€. μλ₯Ό λ€μ΄, μ ν©μ μ λλ€.
μκ° λ³΅μ‘λ: O(1)
// β
λ±μ°¨μμ΄ ν© κ΅¬νκΈ°
function arithmeticSum(firstTerm, commonDiff, n) {
// S_n = n/2 * (2a_1 + (n-1)d)
return (n * (2 * firstTerm + (n - 1) * commonDiff)) / 2
}
// β
첫 νκ³Ό λ§μ§λ§ νμΌλ‘ ν© κ΅¬νκΈ° (λ ν¨μ¨μ )
function arithmeticSumWithLastTerm(firstTerm, lastTerm, n) {
// S_n = n/2 * (a_1 + a_n)
return (n * (firstTerm + lastTerm)) / 2
}
// μ€μ μμ: ν© κ³μ°
arithmeticSum(3, 5, 4) // 4/2 * (2*3 + (4-1)*5) = 2 * (6 + 15) = 42
arithmeticSumWithLastTerm(3, 18, 4) // 4/2 * (3 + 18) = 2 * 21 = 42
μ£Όμμ :
- 곡차(d)κ° 0μ΄λ©΄ λͺ¨λ νμ΄ κ°μ μμ μμ΄μ λλ€.
- ν© κ³΅μμμ λλμ μ μ μ λλμ μ£Όμ (BigInt νμ μ μ¬μ©).
- μμ 곡차λ κ°λ₯ν©λλ€ (κ°μνλ λ±μ°¨μμ΄).
1.6 λ±λΉμμ΄ (Geometric Sequence)
λ±λΉμμ΄μ μ°μνλ λ νμ λΉκ° μΌμ ν μμ΄μ λλ€. 첫 λ²μ§Έ νμ , 곡λΉ(common ratio)λ₯Ό λΌκ³ ν λ:
- μΌλ°ν:
- ν© κ³΅μ: (λ¨, )
- 곡λΉκ° 1μΈ κ²½μ°: (λͺ¨λ νμ΄ κ°μ)
- 무ν λ±λΉμμ΄ ν© (μΌ λ):
λ±λΉμμ΄μ ν©μ ꡬν λλ μ κ³μ°ν΄μΌ νλ―λ‘, λΉ λ₯Έ κ±°λμ κ³± μκ³ λ¦¬μ¦μ μ¬μ©νμ¬ O(log n) μκ°μ κ³μ°ν©λλ€.
μκ° λ³΅μ‘λ: O(log n) (κ±°λμ κ³± κ³μ° ν¬ν¨)
// β
λΉ λ₯Έ κ±°λμ κ³± (Binary Exponentiation)
function power(base, exp) {
if (exp === 0) return 1
if (exp === 1) return base
let result = 1
let current = base
let remaining = exp
while (remaining > 0) {
if (remaining % 2 === 1) {
result *= current
}
current *= current
remaining = Math.floor(remaining / 2)
}
return result
}
// β
λ±λΉμμ΄ ν© κ΅¬νκΈ°
function geometricSum(firstTerm, commonRatio, n) {
if (commonRatio === 1) {
return firstTerm * n // 곡λΉκ° 1μ΄λ©΄ λͺ¨λ νμ΄ κ°μ
}
// S_n = a_1 * (r^n - 1) / (r - 1)
const rn = power(commonRatio, n)
return (firstTerm * (rn - 1)) / (commonRatio - 1)
}
// β
λͺ¨λλ¬ κ±°λμ κ³± (ν° μ μ²λ¦¬)
function modPower(base, exp, mod) {
if (exp === 0) return 1
if (exp === 1) return base % mod
let result = 1n
let current = BigInt(base) % BigInt(mod)
let remaining = BigInt(exp)
while (remaining > 0n) {
if (remaining % 2n === 1n) {
result = (result * current) % BigInt(mod)
}
current = (current * current) % BigInt(mod)
remaining = remaining / 2n
}
return Number(result)
}
// β
λͺ¨λλ¬ μ°μ°κ³Ό ν¨κ» μ¬μ© (ν° μ μ²λ¦¬)
function geometricSumMod(firstTerm, commonRatio, n, mod) {
if (commonRatio === 1) {
return (firstTerm * n) % mod
}
const rn = modPower(commonRatio, n, mod)
const numerator = (firstTerm * (rn - 1 + mod)) % mod // μμ λ°©μ§
const denominator = (commonRatio - 1 + mod) % mod // μμ λ°©μ§
// λͺ¨λλ¬ μμμ μ¬μ©ν λλμ
(νλ₯΄λ§μ μμ 리: modκ° μμμΌ λ)
// (a / b) mod p = (a * b^(p-2)) mod p
const invDenominator = modPower(denominator, mod - 2, mod)
return (numerator * invDenominator) % mod
}
// μ€μ μμ: ν© κ³μ°
geometricSum(2, 3, 4) // 2 * (3^4 - 1) / (3 - 1) = 2 * (81 - 1) / 2 = 80
μ£Όμμ :
- 곡λΉ(r)κ° 1μ΄λ©΄ λͺ¨λ νμ΄ κ°μ μμ μμ΄μ΄λ―λ‘ μ λλ€.
- 곡λΉκ° 0μ΄λ©΄ λ λ²μ§Έ νλΆν° λͺ¨λ 0μ λλ€.
- ν© κ³΅μμμ
r = 1μΈ κ²½μ°λ₯Ό λ³λ μ²λ¦¬ν΄μΌ ν©λλ€. - ν° μ κ³μ° μ BigIntλ λͺ¨λλ¬ μ°μ°μ μ¬μ©ν©λλ€.
- 무ν λ±λΉμμ΄ ν©μ μΌ λλ§ μλ ΄ν©λλ€.
2. νμ μκ³ λ¦¬μ¦
2.1 μ΄μ§ νμ (Binary Search)
μκ° λ³΅μ‘λ: O(log n)
// β
κΈ°λ³Έ μ΄μ§ νμ (μ λ ¬λ λ°°μ΄)
function binarySearch(arr, target) {
let left = 0
let right = arr.length - 1
while (left <= right) {
const mid = Math.floor((left + right) / 2)
if (arr[mid] === target) return mid
if (arr[mid] < target) left = mid + 1
else right = mid - 1
}
return -1 // μ°Ύμ§ λͺ»ν¨
}
// β
Lower Bound (target μ΄μμ 첫 λ²μ§Έ μμΉ)
function lowerBound(arr, target) {
let left = 0
let right = arr.length
while (left < right) {
const mid = Math.floor((left + right) / 2)
if (arr[mid] < target) left = mid + 1
else right = mid
}
return left
}
// β
Upper Bound (target μ΄κ³Όμ 첫 λ²μ§Έ μμΉ)
function upperBound(arr, target) {
let left = 0
let right = arr.length
while (left < right) {
const mid = Math.floor((left + right) / 2)
if (arr[mid] <= target) left = mid + 1
else right = mid
}
return left
}
// μ€μ μμ: μ λ ¬λ λ°°μ΄μμ μ°ΎκΈ°
binarySearch([1, 3, 5, 7, 9], 5) // 2
// μ€μ μμ: λ²μ μ°ΎκΈ°
function findRange(arr, target) {
const lower = lowerBound(arr, target)
const upper = upperBound(arr, target)
return [lower, upper - 1] // [μμ μΈλ±μ€, λ μΈλ±μ€]
}
// μ€μ μμ: νλΌλ©νΈλ¦ μμΉ (쑰건μ λ§μ‘±νλ μ΅λ/μ΅μκ°)
function parametricSearch(arr, condition) {
let left = 0
let right = arr.length - 1
let result = -1
while (left <= right) {
const mid = Math.floor((left + right) / 2)
if (condition(arr[mid])) {
result = mid
left = mid + 1 // μ΅λκ° μ°ΎκΈ°
} else {
right = mid - 1
}
}
return result
}
μ£Όμμ :
- λ°°μ΄μ΄ μ λ ¬λμ΄ μμ΄μΌ ν©λλ€.
left <= rightvsleft < right쑰건μ λ°λΌ λμμ΄ λ€λ¦ λλ€.- μ€λ²νλ‘μ° λ°©μ§:
mid = left + Math.floor((right - left) / 2)
2.2 ν¬ ν¬μΈν° (Two Pointers)
μκ° λ³΅μ‘λ: O(n)
// β
λ μμ ν© μ°ΎκΈ° (μ λ ¬λ λ°°μ΄)
function twoSum(arr, target) {
let left = 0
let right = arr.length - 1
while (left < right) {
const sum = arr[left] + arr[right]
if (sum === target) return [left, right]
if (sum < target) left++
else right--
}
return null
}
// β
μΈ μμ ν© μ°ΎκΈ°
function threeSum(arr, target) {
arr.sort((a, b) => a - b)
const result = []
for (let i = 0; i < arr.length - 2; i++) {
if (i > 0 && arr[i] === arr[i - 1]) continue // μ€λ³΅ μ κ±°
let left = i + 1
let right = arr.length - 1
while (left < right) {
const sum = arr[i] + arr[left] + arr[right]
if (sum === target) {
result.push([arr[i], arr[left], arr[right]])
while (left < right && arr[left] === arr[left + 1]) left++
while (left < right && arr[right] === arr[right - 1]) right--
left++
right--
} else if (sum < target) left++
else right--
}
}
return result
}
// β
μ΅λ κΈΈμ΄ λΆλΆ λ°°μ΄ (μ¬λΌμ΄λ© μλμ°μ μ μ¬)
function maxLengthSubarray(arr, condition) {
let left = 0
let maxLen = 0
for (let right = 0; right < arr.length; right++) {
// 쑰건μ λ§μ‘±νμ§ μμΌλ©΄ left μ΄λ
while (!condition(arr.slice(left, right + 1))) {
left++
}
maxLen = Math.max(maxLen, right - left + 1)
}
return maxLen
}
μ£Όμμ :
- λ°°μ΄μ΄ μ λ ¬λμ΄ μμ΄μΌ ν¨μ¨μ μ λλ€.
- μ€λ³΅ μ κ±°κ° νμν κ²½μ° λ³λ μ²λ¦¬ν©λλ€.
2.3 μ¬λΌμ΄λ© μλμ° (Sliding Window)
μκ° λ³΅μ‘λ: O(n)
// β
κ³ μ ν¬κΈ° μλμ°
function maxSumSubarray(arr, k) {
let windowSum = 0
let maxSum = -Infinity
// μ΄κΈ° μλμ°
for (let i = 0; i < k; i++) {
windowSum += arr[i]
}
maxSum = windowSum
// μλμ° μ¬λΌμ΄λ©
for (let i = k; i < arr.length; i++) {
windowSum = windowSum - arr[i - k] + arr[i]
maxSum = Math.max(maxSum, windowSum)
}
return maxSum
}
// β
κ°λ³ ν¬κΈ° μλμ° (μ΅λ κΈΈμ΄)
function longestSubstringWithoutRepeating(s) {
const seen = new Map()
let left = 0
let maxLen = 0
for (let right = 0; right < s.length; right++) {
const char = s[right]
// μ€λ³΅ λ¬Έμ λ°κ²¬ μ left μ΄λ
if (seen.has(char) && seen.get(char) >= left) {
left = seen.get(char) + 1
}
seen.set(char, right)
maxLen = Math.max(maxLen, right - left + 1)
}
return maxLen
}
// β
μ΅μ κΈΈμ΄ λΆλΆ λ°°μ΄
function minLengthSubarray(arr, target) {
let left = 0
let windowSum = 0
let minLen = Infinity
for (let right = 0; right < arr.length; right++) {
windowSum += arr[right]
while (windowSum >= target) {
minLen = Math.min(minLen, right - left + 1)
windowSum -= arr[left]
left++
}
}
return minLen === Infinity ? 0 : minLen
}
μ£Όμμ :
- μλμ° ν¬κΈ°κ° κ³ μ μΈμ§ κ°λ³μΈμ§μ λ°λΌ ꡬνμ΄ λ€λ¦ λλ€.
- μ€λ³΅ 체ν¬λ
SetλλMapμ μ¬μ©ν©λλ€.
3. κ·Έλν μκ³ λ¦¬μ¦
3.1 Union-Find (Disjoint Set)
μκ° λ³΅μ‘λ: κ±°μ O(1) (κ²½λ‘ μμΆ + λν¬ μ΅μ ν)
class UnionFind {
constructor(n) {
this.parent = Array.from({ length: n }, (_, i) => i)
this.rank = Array(n).fill(0)
}
// κ²½λ‘ μμΆμ μ¬μ©ν find
find(x) {
if (this.parent[x] !== x) {
this.parent[x] = this.find(this.parent[x]) // κ²½λ‘ μμΆ
}
return this.parent[x]
}
// λν¬λ₯Ό μ¬μ©ν union
union(x, y) {
const rootX = this.find(x)
const rootY = this.find(y)
if (rootX === rootY) return false // μ΄λ―Έ κ°μ μ§ν©
// λν¬κ° μμ νΈλ¦¬λ₯Ό ν° νΈλ¦¬μ μ°κ²°
if (this.rank[rootX] < this.rank[rootY]) {
this.parent[rootX] = rootY
} else if (this.rank[rootX] > this.rank[rootY]) {
this.parent[rootY] = rootX
} else {
this.parent[rootY] = rootX
this.rank[rootX]++
}
return true
}
// κ°μ μ§ν©μΈμ§ νμΈ
connected(x, y) {
return this.find(x) === this.find(y)
}
}
// μ€μ μμ: μ°κ²° μμ κ°μ μ°ΎκΈ°
function countComponents(n, edges) {
const uf = new UnionFind(n)
for (const [u, v] of edges) {
uf.union(u, v)
}
const roots = new Set()
for (let i = 0; i < n; i++) {
roots.add(uf.find(i))
}
return roots.size
}
μ£Όμμ :
- κ²½λ‘ μμΆκ³Ό λν¬ μ΅μ νλ₯Ό λͺ¨λ μ¬μ©ν΄μΌ ν¨μ¨μ μ λλ€.
findμμ μ¬κ· νΈμΆ μ κ²½λ‘ μμΆμ΄ μλμΌλ‘ μνλ©λλ€.
3.2 λ€μ΅μ€νΈλΌ μκ³ λ¦¬μ¦ (Dijkstra)
μκ° λ³΅μ‘λ: O((V + E) log V) (μ°μ μμ ν μ¬μ©)
// β
λ€μ΅μ€νΈλΌ μκ³ λ¦¬μ¦
function dijkstra(graph, start) {
const n = graph.length
const dist = Array(n).fill(Infinity)
const visited = Array(n).fill(false)
dist[start] = 0
// μ°μ μμ ν: [거리, λ
Έλ]
const pq = [[0, start]]
while (pq.length > 0) {
// μ΅μ 거리 λ
Έλ μ ν
pq.sort((a, b) => a[0] - b[0])
const [d, u] = pq.shift()
if (visited[u]) continue
visited[u] = true
// μΈμ λ
Έλ μ
λ°μ΄νΈ
for (const [v, weight] of graph[u]) {
if (!visited[v] && dist[u] + weight < dist[v]) {
dist[v] = dist[u] + weight
pq.push([dist[v], v])
}
}
}
return dist
}
// β
μΈμ 리μ€νΈ κ·Έλν μμ
// graph[i] = [[λ
Έλ, κ°μ€μΉ], ...]
const graph = [
[
[1, 4],
[2, 1],
], // 0λ² λ
Έλ: 1λ²(κ°μ€μΉ 4), 2λ²(κ°μ€μΉ 1)
[[3, 2]], // 1λ² λ
Έλ: 3λ²(κ°μ€μΉ 2)
[
[1, 2],
[3, 5],
], // 2λ² λ
Έλ: 1λ²(κ°μ€μΉ 2), 3λ²(κ°μ€μΉ 5)
[], // 3λ² λ
Έλ: μμ
]
// μ€μ μμ: μ΅λ¨ κ²½λ‘ μ°ΎκΈ°
const distances = dijkstra(graph, 0)
// [0, 3, 1, 5] - 0λ²μμ κ° λ
ΈλκΉμ§μ μ΅λ¨ 거리
μ£Όμμ :
- μμ κ°μ€μΉκ° μμΌλ©΄ μ¬μ©ν μ μμ΅λλ€ (벨λ§-ν¬λ μ¬μ©).
- μ€μ λ‘λ ν(Heap) μλ£κ΅¬μ‘°λ₯Ό μ¬μ©νλ κ²μ΄ λ ν¨μ¨μ μ λλ€.
- JavaScriptμμλ λ°°μ΄ μ λ ¬λ‘ λ체ν μ μμ§λ§, μ±λ₯μ΄ λ¨μ΄μ§λλ€.
3.3 νλ‘μ΄λ-μμ μκ³ λ¦¬μ¦ (Floyd-Warshall)
μκ° λ³΅μ‘λ: O(VΒ³)
// β
νλ‘μ΄λ-μμ
μκ³ λ¦¬μ¦ (λͺ¨λ μ μ΅λ¨ κ²½λ‘)
function floydWarshall(graph) {
const n = graph.length
const dist = graph.map((row) => [...row]) // 볡μ¬
// μ€κ° λ
Έλλ₯Ό ν΅ν κ²½λ‘ μ
λ°μ΄νΈ
for (let k = 0; k < n; k++) {
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
if (dist[i][k] !== Infinity && dist[k][j] !== Infinity) {
dist[i][j] = Math.min(dist[i][j], dist[i][k] + dist[k][j])
}
}
}
}
return dist
}
// β
μΈμ νλ ¬ κ·Έλν μμ
// graph[i][j] = iμμ jλ‘ κ°λ κ°μ€μΉ (μμΌλ©΄ Infinity)
const graph = [
[0, 4, 1, Infinity],
[Infinity, 0, Infinity, 2],
[Infinity, 2, 0, 5],
[Infinity, Infinity, Infinity, 0],
]
// μ€μ μμ: λͺ¨λ μ μ΅λ¨ κ²½λ‘
const allPairs = floydWarshall(graph)
μ£Όμμ :
- μμ μ¬μ΄ν΄μ΄ μμΌλ©΄ κ°μ§ν μ μμ΅λλ€ (
dist[i][i] < 0). - κ³΅κ° λ³΅μ‘λκ° O(VΒ²)μ΄λ―λ‘ ν° κ·Έλνμμλ λΉν¨μ¨μ μ λλ€.
4. μ‘°ν©/μμ΄
4.1 μ‘°ν© (Combination)
μκ° λ³΅μ‘λ: O(C(n, r))
// β
μ‘°ν© μμ± (nκ° μ€ rκ° μ ν)
function combinations(arr, r) {
const result = []
function backtrack(start, path) {
if (path.length === r) {
result.push([...path])
return
}
for (let i = start; i < arr.length; i++) {
path.push(arr[i])
backtrack(i + 1, path)
path.pop()
}
}
backtrack(0, [])
return result
}
// β
μ‘°ν© κ°μ κ³μ° (nCr)
function combinationCount(n, r) {
if (r > n || r < 0) return 0
if (r === 0 || r === n) return 1
let result = 1
for (let i = 0; i < r; i++) {
result = (result * (n - i)) / (i + 1)
}
return result
}
// μ€μ μμ: 5κ° μ€ 3κ° μ ν
combinations([1, 2, 3, 4, 5], 3)
// [[1,2,3], [1,2,4], [1,2,5], [1,3,4], ...]
μ£Όμμ :
- ν° μμ μ‘°ν© κ³μ° μ BigIntκ° νμν μ μμ΅λλ€.
- μ€λ³΅μ΄ μλ λ°°μ΄μ λ³λ μ²λ¦¬ν©λλ€.
4.2 μμ΄ (Permutation)
μκ° λ³΅μ‘λ: O(n!)
// β
μμ΄ μμ± (nκ°λ₯Ό λͺ¨λ λμ΄)
function permutations(arr) {
const result = []
function backtrack(path, used) {
if (path.length === arr.length) {
result.push([...path])
return
}
for (let i = 0; i < arr.length; i++) {
if (used[i]) continue
used[i] = true
path.push(arr[i])
backtrack(path, used)
path.pop()
used[i] = false
}
}
backtrack([], Array(arr.length).fill(false))
return result
}
// β
μμ΄ κ°μ κ³μ° (n!)
function permutationCount(n) {
let result = 1
for (let i = 2; i <= n; i++) {
result *= i
}
return result
}
// μ€μ μμ: 3κ° μμ΄
permutations([1, 2, 3])
// [[1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1]]
μ£Όμμ :
n!μ λ§€μ° λΉ λ₯΄κ² μ¦κ°νλ―λ‘ μμ nμλ§ μ¬μ© κ°λ₯ν©λλ€.- μ€λ³΅μ΄ μλ λ°°μ΄μ λ³λ μ²λ¦¬ν©λλ€.
5. νΈλ¦¬ μν
5.1 DFS (κΉμ΄ μ°μ νμ)
// β
μ¬κ· DFS
function dfsRecursive(node, visited = new Set()) {
if (!node || visited.has(node)) return
visited.add(node)
// λ
Έλ μ²λ¦¬
console.log(node.val)
// μμ λ
Έλ μν
for (const child of node.children) {
dfsRecursive(child, visited)
}
}
// β
μ€νμ μ¬μ©ν λ°λ³΅ DFS
function dfsIterative(root) {
const stack = [root]
const visited = new Set()
while (stack.length > 0) {
const node = stack.pop()
if (!node || visited.has(node)) continue
visited.add(node)
// λ
Έλ μ²λ¦¬
console.log(node.val)
// μμ λ
Έλλ₯Ό μμμΌλ‘ μ€νμ μΆκ°
for (let i = node.children.length - 1; i >= 0; i--) {
stack.push(node.children[i])
}
}
}
5.2 BFS (λλΉ μ°μ νμ)
// β
νλ₯Ό μ¬μ©ν BFS
function bfs(root) {
const queue = [root]
const visited = new Set()
while (queue.length > 0) {
const node = queue.shift()
if (!node || visited.has(node)) continue
visited.add(node)
// λ
Έλ μ²λ¦¬
console.log(node.val)
// μμ λ
Έλλ₯Ό νμ μΆκ°
for (const child of node.children) {
queue.push(child)
}
}
}
// β
λ λ²¨λ³ BFS
function bfsLevelOrder(root) {
if (!root) return []
const result = []
const queue = [root]
while (queue.length > 0) {
const levelSize = queue.length
const level = []
for (let i = 0; i < levelSize; i++) {
const node = queue.shift()
level.push(node.val)
for (const child of node.children) {
queue.push(child)
}
}
result.push(level)
}
return result
}
π‘ μ€μ νμ© ν
1. μκ³ λ¦¬μ¦ μ ν κ°μ΄λ
- μ λ ¬λ λ°°μ΄μμ μ°ΎκΈ°: μ΄μ§ νμ
- λ μμ ν©/μ°¨ μ°ΎκΈ°: ν¬ ν¬μΈν°
- μ°μ λΆλΆ λ°°μ΄ μ΅μ ν: μ¬λΌμ΄λ© μλμ°
- κ·Έλν μ°κ²°μ±: Union-Find
- μ΅λ¨ κ²½λ‘ (λ¨μΌ μΆλ°): λ€μ΅μ€νΈλΌ
- μ΅λ¨ κ²½λ‘ (λͺ¨λ μ): νλ‘μ΄λ-μμ
- μμ κ΄λ ¨: μλΌν μ€ν λ€μ€μ 체
- μ΅λ곡μ½μ/μ΅μ곡배μ: μ ν΄λ¦¬λ νΈμ λ²
2. μ΅μ ν ν
- BigInt μ¬μ©: ν° μ κ³μ° μ (μ‘°ν©, μμ΄, μ΅μ곡배μ)
- λ©λͺ¨μ΄μ μ΄μ : λ°λ³΅ κ³μ°μ΄ λ§μ κ²½μ° (νΌλ³΄λμΉ, μ‘°ν©)
- κ²½λ‘ μμΆ: Union-Findμμ νμ
- μ‘°κΈ° μ’ λ£: 쑰건 λ§μ‘± μ μ¦μ λ°ν
3. μμ£Ό μ€μνλ λΆλΆ
- μ΄μ§ νμμμ
left <= rightvsleft < rightκ΅¬λΆ - ν¬ ν¬μΈν°μμ μ€λ³΅ μ κ±° μ²λ¦¬
- Union-Findμμ κ²½λ‘ μμΆ λλ½
- λ€μ΅μ€νΈλΌμμ μμ κ°μ€μΉ μ²λ¦¬ λΆκ°
- μ‘°ν©/μμ΄μμ ν° μ μ€λ²νλ‘μ°