[Algorithm] ์ ํด๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ / ์์ธ์๋ถํด๋ก ์ต์๊ณต๋ฐฐ์ ์ต๋๊ณต์ฝ์ ๊ณ์ฐํ๊ธฐ
N๊ฐ์ ์ต์๊ณต๋ฐฐ์
ํ๋ก๊ทธ๋๋จธ์ค ๋ ๋ฒจ 2์ 12953๋ฒ ๋ฌธ์ ๋ N๊ฐ์ ์ต์๊ณต๋ฐฐ์๋ฅผ ๊ตฌํ๋ ๋ฌธ์ ๋ค. ์ต์๊ณต๋ฐฐ์๋ ์ ๋ ฅ๋ ๋ ์์ ๋ฐฐ์ ์ค ๊ณตํต์ด ๋๋ ๊ฐ์ฅ ์์ ์ซ์๋ฅผ ์๋ฏธํ๋ค. ์๋ฅผ๋ค์ด 2์ 7์ ์ต์๊ณต๋ฐฐ์๋ 14๊ฐ ๋๋ค.
์ฃผ์ด์ง ๋ฐฐ์ด(arr
)์์ ๊ฐ์ฅ ํฐ ์์ ๋ฐฐ์๋ฅผ ๋๋จธ์ง ์์์ ๋๋ด์ ๋ ๋ชจ๋ 0์ด ๋๋ ์๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ์ผ๋ก ํ์์ง๋ง, ๋งค๋ฒ ํฐ ์๋ฅผ ์ ์ธํ ๋ฐฐ์ด์ ๋ชจ๋ ์ซ์๋ฅผ ํ๋์ฉ ๋๋ ๋ด์ผ ํ๊ธฐ ๋๋ฌธ์ ํจ์จ์ ์ด์ง ์๋ค. ๋ฐฐ์ด ์ ๋ ฌ์ ์ ์ธํ๊ณ ๋ฐฐ์ด ๊ธธ์ด๊ฐ n
, while๋ฌธ์ ๋ฐ๋ณต ํ์๊ฐ x
์ด๋ผ๊ณ ํ์ ๋ ์๊ฐ๋ณต์ก๋๋ $O(n \cdot x)$๊ฐ ๋๋ค.
function solution(arr) {
const sortedArray = arr.sort((a, b) => b - a);
const [biggest, ...rest] = sortedArray;
const isDivisible = (target) => rest.every((n) => target % n === 0);
let lcmFound = false;
let multiplier = 1;
let leastCommonMultiple = -1;
while (!lcmFound) {
const currentNum = biggest * multiplier;
lcmFound = isDivisible(currentNum);
if (lcmFound) leastCommonMultiple = currentNum;
multiplier++;
}
return leastCommonMultiple;
}
solution([1, 2, 3]); // 6
// 1: 1, 2, 3, 4, 5, 6, ...
// 2: 2, 4, 6, 8, ...
// 3: 3, 6, 9, 12, ...
์ ํด๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ
๋ค๋ฅธ ์ฌ๋์ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ ์ค, ์ ํด๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ฉด (๋๋ต)๋ก๊ทธ ์๊ฐ ๋ณต์ก๋๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ ๊ฒ์ ๋ฐ๊ฒฌํ๋ค. a
, b
๋ ์์ ๊ณฑ์, ๋ ์์ ์ต๋๊ณต์ฝ์๋ก ๋๋ ์ ์ต์๊ณต๋ฐฐ์๋ฅผ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ์ด๋ค.
// ์ต๋๊ณต์ฝ์(Greatest Common Divisor, GCD) ์ฐพ๊ธฐ
function gcd(a, b) {
if (b === 0) return a;
return gcd(b, a % b);
}
// ์ต์๊ณต๋ฐฐ์(Least Common Multiple, LCM) ์ฐพ๊ธฐ
function lcm(a, b) {
return (a * b) / gcd(a, b);
}
function solution(arr) {
let result = arr[0];
for (let i = 1; i < arr.length; i++) {
result = lcm(result, arr[i]);
}
return result;
}
solution([1, 2, 3]); // 6
์ ์ฝ๋์์ ์ต๋๊ณต์ฝ์๋ฅผ ๊ณ์ฐํ๋ ๋ถ๋ถ์ ์ ํด๋ฆฌ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์ ์ฉ๋๋ค. ์ต๋๊ณต์ฝ์๋ ๋ ์(ํน์ ๊ทธ ์ด์)๊ฐ ๊ณตํต์ผ๋ก ๊ฐ์ง๋ ์ฝ์ ์ค ๊ฐ์ฅ ํฐ ์๋ฅผ ์๋ฏธํ๋ค(๋ ์๊ฐ ๋์์ ๋๋์ด ๋จ์ด์ง๋ ๊ฐ์ฅ ํฐ ์). ์ฝ์๋ ์ด๋ค ์๋ฅผ ๋๋์ด ๋จ์ด์ง๊ฒ ํ๋ ์(๋๋จธ์ง 0)์ด๋ค.
๐ก mod๋ ๋๋จธ์ง ์ฐ์ฐ์ ์๋ฏธํ๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ %
์ฐ์ฐ์์ ๋์ผํ๋ค.
์ ํด๋ฆฌ๋ ํธ์ ๋ฒ์ a
, b
๋ ์๊ฐ ์ฃผ์ด์ก์ ๋ b
์ a mod b
์ ์ต๋๊ณต์ฝ์๋ a
, b
์ ์ต๋๊ณต์ฝ์์ ๋์ผํ๋ค๋ ํน์ฑ์ ์ด์ฉํ ๋ฐฉ๋ฒ์ด๋ค. ์ฆ, ๋ ์ ์์ ์ต๋๊ณต์ฝ์๋ ๋์ผํ๊ฒ ์ ์งํ๋ฉด์, ๋ ์ ์๋ฅผ ์๊ฒ ๋ง๋๋ ์๋ฆฌ๋ผ๊ณ ๋ณผ ์ ์๋ค.
์๋ฅผ ๋ค์ด, 172์ 36์ ๋ณด์. ๋ ์์ ์ต๋๊ณต์ฝ์๋ 4์ด๋ค. 4์ 24์ ์ต๋๊ณต์ฝ์๋ 4์ด๋ค.
4์ 24์ ์ต๋๊ณต์ฝ์๋ ์ต๋ 4๋ฅผ ๋์ ์ ์๋ค. 24= 4 · 6. ๋ฐ๋ผ์ ๋ ์์ ์ต๋๊ณต์ฝ์๋ 4์ด๋ค.
172์ 36์ ์ต๋๊ณต์ฝ์๊ฐ 4์์ ํ์ธํ๋ ๊ฒ๋ณด๋ค 4์ 24์ ์ต๋๊ณต์ฝ์๊ฐ 4์์ ๋ณด์ด๋ ๊ฒ์ด ๋ ์ฝ๋ค.
์ ๊ทธ๋ด๊น? ๊ทธ๊ฒ์ 172, 36๋ณด๋ค 4, 24์ ํฌ๊ธฐ๊ฐ ๋ ์๊ธฐ ๋๋ฌธ์ด๋ค.
๋ฐ๋ผ์ 172์ 36์ ์ต๋๊ณต์ฝ์๋ฅผ ์ ์งํ๋ฉด์, ๋ ์ 172, 36์ ๋ ์๊ฒ ๋ง๋ ๋ค๋ฉด,
172์ 36์ ์ต๋๊ณต์ฝ์๋ฅผ ์ข ๋ ์ฝ๊ฒ ํ์ธํ ์ ์์ ๊ฒ์ด๋ค.
์ฐธ๊ณ ๋ก a
๊ฐ b
๋ณด๋ค ์๋ค๋ฉด, ํญ์ ์ฒซ ๋ฒ์งธ ์ฌ๊ท ํธ์ถ์์ a
์ b
์ ์์น๊ฐ ๋ฐ๋๋ค. ๋ฐ๋ผ์ ๋ ์ธ์์ ์์๋ ์ค์ํ์ง ์๋ค.
์ต๋๊ณต์ฝ์์ ์ต์๊ณต๋ฐฐ์์ ๊ด๊ณ
์ต๋๊ณต์ฝ์(GCD)์ ์ต์๊ณต๋ฐฐ์(LCM)๋ ํน๋ณํ ๊ด๊ณ๋ฅผ ๊ฐ๋๋ค. a
, b
๋ ์๊ฐ ์ฃผ์ด์ก์ ๋ a
,b
์ ์ต๋๊ณต์ฝ์์ ์ต์๊ณต๋ฐฐ์๋ฅผ ๊ณฑํ ๊ฐ์ a
, b
๋ฅผ ๊ณฑํ ๊ฐ๊ณผ ๋์ผํ๋ค.
$$a \times b=GCD(a,b) \times LCM(a,b)$$
์๋ฅผ๋ค์ด a
๊ฐ 48, b
๊ฐ 18๋ผ๋ฉด, ์ด ๋ ์์ ๊ณฑ์ 864์ด๊ณ , ์ด๋ ๋ ์์ ์ต๋๊ณต์ฝ์ 6๊ณผ ์ต์๊ณต๋ฐฐ์ 144๋ฅผ ๊ณฑํ ๊ฐ๊ณผ ๊ฐ๋ค.
$$\begin{align*}a &= 48, \quad b = 18 \\a \times b &= 864 \\\text{GCD}(48, 18) &= 6 \\\text{LCM}(48, 18) &= 144 \\\text{GCD}(48, 18) \times \text{LCM}(48, 18) &= 864\end{align*}$$
์ด๋ฌํ ๊ด๊ณ๋ฅผ ์ด์ฉํ์ฌ ๋ ์์ ์ต๋๊ณต์ฝ์๋ฅผ ์๊ณ ์์ ๋ ์ต์๊ณต๋ฐฐ์๋ฅผ ๋ ์ฝ๊ฒ ์ฐพ์ ์ ์๋ค. ๊ทธ ๋ฐ๋์ ๊ฒฝ์ฐ๋ ๋ง์ฐฌ๊ฐ์ง๋ค.
โถ ์ต๋๊ณต์ฝ์๋ฅผ ์๊ณ ์์ ๋ ์ต์๊ณต๋ฐฐ์ ๊ตฌํ๊ธฐ
$$LCM(a,b)=\frac{a \times b}{GCD(a,b)}$$
โท ์ต์๊ณต๋ฐฐ์๋ฅผ ์๊ณ ์์ ๋ ์ต๋๊ณต์ฝ์ ๊ตฌํ๊ธฐ
$$GCD(a,b)=\frac{a \times b}{LCM(a,b)}$$
์ ๋ด์ฉ์ ์ฝ๋๋ก ํ์ด๋ณด๋ฉด ์๋์ ๊ฐ๋ค. 48(a
)๊ณผ 18(b
)์ ์ต๋๊ณต์ฝ์ 6์ ์๊ณ ์์ ๋ ์ด ๋์ ๊ณฑ 864๋ฅผ ์ต๋๊ณต์ฝ์ 6์ผ๋ก ๋๋๋ฉด ์ต์๊ณต๋ฐฐ์๋ฅผ ๊ณ์ฐํ ์ ์๋ค.
// ์ต๋๊ณต์ฝ์(Greatest Common Divisor, GCD) ์ฐพ๊ธฐ
function gcd(a, b) {
if (b === 0) return a;
return gcd(b, a % b);
}
// ์ต์๊ณต๋ฐฐ์(Least Common Multiple, LCM) ์ฐพ๊ธฐ
function lcm(a, b) {
return (a * b) / gcd(a, b);
}
์์ธ์๋ถํด๋ก GCD / LCM ๊ณ์ฐํ๊ธฐ
์์ธ์๋ถํด๋ ์ฃผ์ด์ง ์ ์๋ฅผ ๋ ์ด์ ๋๋ ์ ์๋ ์์๋ค์ ๊ณฑ์ผ๋ก ํํํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
์์๋ 1๊ณผ ์๊ธฐ ์์ ๋ง์ผ๋ก ๋๋์ด ๋จ์ด์ง๋ 1๋ณด๋ค ํฐ ์์ฐ์๋ก 2, 3, 5, 7, 11 ๋ฑ์ด ์๋ค. ์์ธ์๋ ์ด๋ค ์ ์๋ฅผ ์์๋ค์ ๊ณฑ์ผ๋ก ํํํ ๋ ์ฌ์ฉ๋๋ ์์๋ค์ ๋งํ๋ค. ์๋ฅผ๋ค์ด 48์ ์์ธ์๋ถํดํ๋ฉด 2โด × 3์ด ๋๊ณ , ์ด๋ ์์ธ์๋ 2, 3์ด๋ค.
์์ธ์๋ถํด๋ ๊ฐ์ฅ ์์ ์์์ธ 2๋ถํฐ ์์ํ์ฌ ์ฃผ์ด์ง ์ซ์๋ฅผ ๋๋๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ(๋ชซ)์ ๊ธฐ๋กํ๋ค. 2๋ก ๋ ์ด์ ๋๋์ด ๋จ์ด์ง์ง ์์ผ๋ฉด ๊ทธ ๋ค์ ์์์ธ 3์ผ๋ก ๋๋๊ธฐ๋ฅผ ์๋ํ๋ค. ์ฃผ์ด์ง ์ซ์๋ฅผ ๋ ์ด์ ๋๋ ์ ์์ ๋๊น์ง ์ด ๊ณผ์ ์ ๋ฐ๋ณตํ๋ค.
์๋๋ ์ฃผ์ด์ง ์ ์ n
์ ์์ธ์๋ฅผ ์ฐพ์ ๋ฐฐ์ด๋ก ๋ฐํํ๋ ํจ์. primeFactors
ํจ์์์ remainder
๊ฐ i
๋ก ๋๋์ด ๋จ์ด์ง์ง ์์ผ๋ฉด i
๋ฅผ 1์ฉ ์ฆ๊ฐ์ํค๋๋ฐ, ์ด๋ i
๊ฐ ์์์ธ์ง ๋ฐ๋ก ํ๋ณํ์ง ์์๋ ๋๋ค.
const primeFactors = (n) => {
const result = [];
let remainder = n;
let i = 2;
while (remainder > 1) {
if (remainder % i === 0) {
result.push(i);
remainder /= i;
} else i++;
}
return result;
};
const getFactorsWithExponents = (n) => {
const factors = primeFactors(n); // [ 2, 2, 2, 2, 3 ]
return factors.reduce((acc, cur) => {
acc[cur] = (acc[cur] ?? 0) + 1;
return acc;
}, {});
};
getFactorsWithExponents(48); // { 2: 4, 3: 1 } -> 2โด × 3
i
๊ฐ ์์๊ฐ ์๋ ๊ฒฝ์ฐ, ์๋ฅผ ๋ค์ด 4, 6, 8, 9 ๋ฑ์ ์ซ์๋ ์ด๋ฏธ ์ด์ ๋จ๊ณ์์ ํด๋น ์ซ์๋ค์ ์์ธ์(2, 3, ...)๊ฐ remainder
๋ฅผ ๋๋์๊ธฐ ๋๋ฌธ์ remainder
๋ ๋ ์ด์ i
๋ก ๋๋์ด ๋จ์ด์ง์ง ์๊ฒ ๋๋ค. ๋ฐ๋ผ์ i
๊ฐ ์์๊ฐ ์๋ ์ซ์์ผ ๋ ์์ฐ์ค๋ฝ๊ฒ ๊ฑด๋๋ฐ๊ฒ ๋๋ค.
์ต๋๊ณต์ฝ์
์์ธ์๋ถํด ๊ฒฐ๊ณผ๋ฅผ ํ์ฉํ๋ฉด ์ต๋๊ณต์ฝ์(GCD)์ ์ต์๊ณต๋ฐฐ์(LCM)๋ฅผ ์ฝ๊ฒ ์ฐพ์ ์ ์๋ค.
๋ ์์ ๊ณตํต ์์ธ์๋ค ์ค์์, ์ต์ ์ง์๋ฅผ ์ ํํ์ฌ ๊ณฑํ ๊ฐ
const gcd = (a, b) => {
const factorsA = getFactorsWithExponents(a); // { 2: 4, 3: 1 }
const factorsB = getFactorsWithExponents(b); // { 2: 1, 3: 2 }
let result = 1;
for (const factor in factorsA) {
// ํ๋กํ ํ์
์ฒด์ธ์ผ๋ก ์์๋ ์์ฑ์ด ๊ฐ์ฒด ์์ฑ์ธ ๊ฒ์ฒ๋ผ ์ทจ๊ธ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํ ์กฐ๊ฑด
if (Object.hasOwn(factorsA, factor)) {
const [A, B] = [factorsA[factor], factorsB[factor]];
if (A && B) result *= factor ** Math.min(A, B);
}
}
return result;
};
gcd(48, 18); // 6
๐ Object.hasOwn
, Object.prototype.hasOwnProperty
๋ ๋ฉ์๋๋ ๊ฐ์ฒด๊ฐ ํน์ ์์ฑ์ ๊ฐ์ง๊ณ ์๋์ง ํ์ธํ๋ค. ํ์ง๋ง Object.hasOwn
์ Object
์ ์ ์ ๋ฉ์๋์ฌ์ ์ค๋ฒ๋ผ์ด๋ฉ(์ฌ์ ์) ์ด์๊ฐ ๋ฐ์ํ์ง ์๋๋ค. ์๋ ์์ ์์ ๋ณผ ์ ์๋ฏ์ด Object.prototype.hasOwnProperty
๋ ์ค๋ฒ๋ผ์ด๋ฉ๋ ๋ฉ์๋์ ์ํฅ์ ๋ฐ์ ์์๋๋ก ์๋ํ์ง ์๊ณ ์๋ค.
const user = {
age: 30,
hasOwnProperty: () => 'user์ ์ ์๋ hasOwnProperty',
hasOwn: () => 'user์ ์ ์๋ hasOwn',
};
console.log(Object.hasOwn(user, 'age')); // true
console.log(user.hasOwnProperty('age')); // 'user์ ์ ์๋ hasOwnProperty'
์ต์๊ณต๋ฐฐ์
๋ ์๊ฐ ๊ฐ๋ ๋ชจ๋ ์์ธ์๋ค ์ค์์, ์ต๋ ์ง์๋ฅผ ์ ํํ์ฌ ๊ณฑํ ๊ฐ
const lcm = (a, b) => {
const factorsA = getFactorsWithExponents(a); // { 2: 4, 3: 1 }
const factorsB = getFactorsWithExponents(b); // { 2: 1, 3: 2 }
let result = 1;
const allFactors = { ...factorsA, ...factorsB }; // { 2: 1, 3: 2 }
for (const factor in allFactors) {
if (Object.hasOwn(allFactors, factor)) {
const [A, B] = [factorsA[factor], factorsB[factor]];
result *= factor ** Math.max(A ?? 0, B ?? 0);
}
}
return result;
};
lcm(48, 18); // 144
๊ธ ์์ ์ฌํญ์ ๋ ธ์ ํ์ด์ง์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ๋ฐ์๋ฉ๋๋ค. ๋งํฌ๋ฅผ ์ฐธ๊ณ ํด ์ฃผ์ธ์
'๐ช Programming' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote
๋ค๋ฅธ ๊ธ
-
[Algorithm] ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ — ์ต๋จ ๊ฒฝ๋ก ์ฐพ๊ธฐ
[Algorithm] ๋ค์ต์คํธ๋ผ ์๊ณ ๋ฆฌ์ฆ — ์ต๋จ ๊ฒฝ๋ก ์ฐพ๊ธฐ
2024.05.28 -
[CS] ์ปดํจํฐ์ ์ค์(Real Number) ํํ - ๊ณ ์ ์์์ , ๋ถ๋ ์์์ , ์ง์ ํ๊ธฐ๋ฒ, ์ ๊ทํ ์ด ์ ๋ฆฌ
[CS] ์ปดํจํฐ์ ์ค์(Real Number) ํํ - ๊ณ ์ ์์์ , ๋ถ๋ ์์์ , ์ง์ ํ๊ธฐ๋ฒ, ์ ๊ทํ ์ด ์ ๋ฆฌ
2024.05.27 -
[TS] ํ์ ์คํฌ๋ฆฝํธ ๊ตฌ์กฐ์ ํ์ดํ ํ์ฉํ๊ธฐ
[TS] ํ์ ์คํฌ๋ฆฝํธ ๊ตฌ์กฐ์ ํ์ดํ ํ์ฉํ๊ธฐ
2024.05.25 -
[Algorithm] ๋ ๋ฐ๋จน๊ธฐ ์๊ณ ๋ฆฌ์ฆ / ๋์ ๊ณํ๋ฒ
[Algorithm] ๋ ๋ฐ๋จน๊ธฐ ์๊ณ ๋ฆฌ์ฆ / ๋์ ๊ณํ๋ฒ
2024.05.25