동적 프로그래밍
걸음 수를 채우는 방법
n걸음 거리가 주어졌을 떄 한 걸음, 두 걸음, 세 걸음을 가지고 n걸을음 채우는 여러 방법이 존재한다. 몇 가지 조합니 가능한지 구해라.
일반적인 방법
function waysToCoverSteps(step) {
if (step < 0) return 0;
if (step === 0) return 1;
return (
waysToCoverSteps(step - 1) +
waysToCoverSteps(step - 2) +
waysToCoverSteps(step - 3)
);
}
동적 프로그래밍
function wayToCoverStepsDP(step) {
const cache = {};
if (step < 0) return 0;
if (step == 0) return 1;
if (cache[step]) {
return cache[step];
} else {
cache[step] =
wayToCoverStepsDP(step - 1) +
wayToCoverStepsDP(step - 2) +
wayToCoverStepsDP(step - 3);
return cache[step];
}
}
function wayToCoverStepsDP(stepArr, stepType, stepValue) {
const dpMatrix = new Array(stepValue + 1)
.fill(null)
.map(() => new Array(stepType).fill(undefined));
dpMatrix[0].fill(1);
for (let i = 1; i <= stepValue; i += 1) {
for (let j = 0; j <= stepType; j += 1) {
const temp1 = i - stepArr[j] >= 0 ? dpMatrix[i - stepArr[j]][j] : 0;
const temp2 = j >= 1 ? dpMatrix[i][j - 1] : 0;
dpMatrix[i][j] = temp1 + temp2;
}
}
return dpMatrix[stepValue][stepType - 1];
}
function wayToCoverStepsDPWrapper(stepArr, stepValue) {
return wayToCoverStepsDP(stepArr, stepArr.length, stepValue);
}
배낭 문제 알고리즘
무게와 가치를 지니는 n개의 항목이 주어졌을 때 최대 w의 무개를 담을 수 잇는 배낭에 해당 항목들을 집어넣어 배낭에 담긴 함목들의 가치의 합이 최대가 되도록 한다,
일반적인 방법
function knapsackNavie(index, weight, values, target) {
let result = 0;
if (index <= -1 || target <= 0) {
result = 0;
} else if (weight[index] > target) {
result = knapsackNavie(index - 1, weight, values, target);
} else {
const cur = knapsackNavie(index - 1, weight, values, target);
const other =
values[index] +
knapsackNavie(index - 1, weight, values, target - weight[index]);
result = Math.max(cur, other);
}
return result;
}
동적 알고리즘
function knapsackKDP(index, weight, values, target, matrixDP) {
let result = 0;
if (matrixDP[index + "-" + target]) {
return matrixDP[index + "-" + target];
}
if (index <= -1 || target <= 0) {
result = 0;
} else if (weight[index] < target) {
result = knapsackKDP(index - 1, weight, values, target, matrixDP);
} else {
const cur = knapsackKDP(index - 1, weight, values, target);
const other =
values[index] +
knapsackKDP(index - 1, weight, values, target - weight[index]);
result = Math.max(cur, other);
}
matrixDP[index + "-" + target] = result;
return result;
}
function wayToCoverStepsDP(weight, values, num, target) {
const matrixDP = new Array(target + 1)
.fill(null)
.map(() => new Array(num).fill(undefined));
matrixDP[0].fill(0);
for (let i = 1; i <= target; i += 1) {
for (let j = 0; j < num; j += 1) {
let temp1 = i - weight[j] >= 0 ? values[j] : 0;
let temp2 = j >= 1 ? matrixDP[i][j - 1] : 0;
if (j >= 1 && i - weight[j] >= 0) temp1 += matrixDP[i - weight[j]][j - 1];
matrixDP[i][j] = Math.max(temp1, temp2);
console.log(matrixDP);
}
}
return matrixDP[target][num - 1];
}
function wayToCoverStepsDPWrapper(weight, values, target) {
return wayToCoverStepsDP(weight, values, values.length, target);
}
최장 공통 부분 수열 알고리즘
두 개의 수열이 잇을 때 두 수열의 가장 긴 공통 부분 수열의 길이를 찾습니다. 이때 부분 수열 내 항목들이 연속일 필요는 없고 순서만 맞으면 됩니다.
일반적인 방법
function LCSNaive(str1, str2, str1Length, str2Length) {
if (str1Length === 0 || str2Length === 0) return 0;
if (str1[str1Length - 1] === str2[str2Length - 1]) {
return 1 + LCSNaive(str1, str2, str1Length - 1, str2Length - 1);
} else {
return Math.max(
LCSNaive(str1, str2, str1Length, str2Length - 1),
LCSNaive(str1, str2, str1Length - 1, str2Length)
);
}
}
function LCSNaiveWrapper(str1, str2) {
return LCSNaive(str1, str2, str1.length, str2.length);
}
동적 알고리즘
function logestCommonSequesnceLength(str1, str2) {
const rowLength = str1.length + 1;
const colLength = str2.length + 1;
const matrix = new Array(rowLength)
.fill(null)
.map(() => new Array(colLength).fill(0));
for (let i = 1; i < rowLength; i += 1) {
for (let j = 1; j < colLength; j += 1) {
const str1Char = str1.charAt(i - 1);
const str2Char = str2.charAt(j - 1);
if (str1Char === str2Char) {
matrix[i][j] = matrix[i - 1][j - 1] + 1;
} else {
matrix[i][j] = Math.max(matrix[i - 1][j], matrix[i][j - 1]);
}
}
}
return matrix[rowLength][colLength];
}
동전 교환 알고리즘
동전의 금액 종류가 S={S1, S2, ...Sm}으로 M개이고 각 금액의 동전이 무한 개로 제공될 수 있다고 할 때, 금액 n을 동전으로 교환하기 위한 동전의 조합은 몇 개나 될까? 이 떄 동전의 순서는 무시한다.
일반적인 방법
function countCoinWays(coinArr, numCoins, coinValue) {
if (coinValue === 0) return 1;
if (coinValue < 0 || numCoins <= 0) return 0;
return (
countCoinWays(coinArr, numCoins - 1, coinValue) +
countCoinWays(coinArr, numCoins, coinValue - coinArr[numCoins - 1])
);
}
function countCoinWaysWrapper(coinArr, coinValue) {
return countCoinWays(coinArr, coinArr.length, coinValue);
}
동적 알고리즘
function countCoinWaysDP(coinArr, numCoins, coinValue) {
const dpMatrix = new Array(coinValue + 1)
.fill(null)
.map(() => new Array(numCoins).fill(undefined));
dpMatrix[0].fill(1);
for (let i = 1; i <= coinValue; i += 1) {
for (let j = 0; j < numCoins; j += 1) {
const temp1 = i - coinArr[j] >= 0 ? dpMatrix[i - coinArr[j]][j] : 0;
const temp2 = j >= 1 ? dpMatrix[i][j - 1] : 0;
dpMatrix[i][j] = temp1 + temp2;
}
}
return dpMatrix[coinValue][numCoins - 1];
}
function countCoinWaysDPWrapper(coinArr, coinValue) {
return countCoinWaysDP(coinArr, coinArr.length, coinValue);
}
동적 알고리즘 축소
function solution(n, money) {
const matrix = new Array(n + 1).fill(0);
for (let i = 0; i <= n; i += money[0]) {
matrix[i] = 1;
}
for (let i = 1; i < money.length; i += 1) {
for (let j = money[i]; j <= n; j += 1) {
matrix[j] += matrix[j - money[i]];
}
}
return matrix[n];
}
편집 거리 알고림즘
길이 m인 문자열 str1과 길이 n인 문자열 str2가 주어졌을 때 str1을 str2로 변환하기 위한 최소 편집 횟수는 무엇인가?
일반적인 방법
function editDistanceRecursive(str1, str2, length1, length2) {
if (length1 === 0) return length2;
if (length2 === 0) return length1;
if (str1[length1 - 1] === str2[length2 - 1]) {
return editDistanceRecursive(str1, str2, length1 - 1, length2 - 1);
}
return (
1 +
Math.min(
editDistanceRecursive(str1, str2, length1, length2 - 1),
editDistanceRecursive(str1, str2, length1 - 1, length2),
editDistanceRecursive(str1, str2, length1 - 1, length2 - 1)
)
);
}
function editDistanceRecursiveWrapper(str1, str2) {
return editDistanceRecursive(str1, str2, str1.length, str2.length);
}
동적 프로그래밍
function editDistanceDP(str1, str2, length1, length2) {
const dpMatrix = new Array(length1 + 1)
.fill(undefined)
.map(() => new Array(length2 + 1).fill(undefined));
for (let i = 0; i <= length1; i += 1) {
for (let j = 0; j <= length2; j += 1) {
if (i === 0) {
dpMatrix[i][j] = j;
} else if (j === 0) {
dpMatrix[i][j] = i;
} else if (str1[i - 1] === str2[j - 1]) {
dpMatrix[i][j] = dpMatrix[i - 1][j - 1];
} else {
dpMatrix[i][j] =
1 +
Math.min(
dpMatrix[i][j - 1],
dpMatrix[i - 1][j],
dpMatrix[i - 1][j - 1]
);
}
}
}
console.log(dpMatrix);
return dpMatrix[length1][length2];
}
function editDistanceDPWrapper(str1, str2) {
return editDistanceDP(str1, str2, str1.length, str2.length);
}