Youtube 코드 없는 프로그래밍 DP 플레이리스트 따라서,
LeetCode DP 초급 문제 풀이
Decode Ways는 초급치고는 난이도가 좀 있었다
이전 식에서 계산된 값
들을 가지고 연산하기 때문에이전 식에서 계산된 값
들을 배열 등 자료구조에 저장해놔야 빠른 연산이 가능하다/**
* @param {number[]} cost
* @return {number}
*/
const minCostClimbingStairs = (cost) => {
const accs = [cost[0], cost[1]];
const SIZE = cost.length;
let i = 2;
while (i < SIZE) {
accs[i] = Math.min(accs[i - 1], accs[i - 2]) + cost[i];
i++;
}
return Math.min(accs[SIZE - 1], accs[SIZE - 2]);
};
/**
* @param {number[][]} grid
* @return {number}
*/
const minPathSum = (grid) => {
const m = grid.length;
const n = grid[0].length;
for (const row in grid) {
for (const col in grid[row]) {
if (row === "0" && col === "0") continue;
if (row === "0") grid[row][col] += grid[row][col - 1];
else if (col === "0") grid[row][col] += grid[row - 1][col];
else {
grid[row][col] += Math.min(grid[row - 1][col], grid[row][col - 1]);
}
}
}
return grid[m - 1][n - 1];
};
특정 target을 만들수 있는 동전의 수 = min( (target-각 동전 값)에서 만들 수 있는 동전수) + 1
/**
* @param {number[]} coins
* @param {number} amount
* @return {number}
*/
const coinChange = (coins, amount) => {
const res = Array(amount + 1).fill();
res[0] = 0;
let cur = 0;
while (cur <= amount) {
// cur == 현재 단계의 target number
cur++;
// 일단 1개로 입력
// 현재 단계가 coins에 있으면 한번에 가능하므로 바로 다음 단계로 이동
res[cur] = 1;
if (coins.includes(cur)) continue;
// 동전 배열 순회하면서
// 범위가 맞지 않거나 이전 단계에서 생성 불가능했다면 continue
// 이전 단계에서 생성 가능했다면 해당 가지 수를 추가
const temp = [];
for (const coin of coins) {
if (cur - coin < 0) continue;
if (res[cur - coin] === -1) continue;
temp.push(res[cur - coin]);
}
// 이전 단계에서 모두 생성 불가능했다면, 이번 단계에서도 생성 불가능하므로 -1
// 생성 가능한 경우의 수 중 최소값 입력
temp.length === 0 ? (res[cur] = -1) : (res[cur] += Math.min(...temp));
}
return res[amount];
};
/**
* @param {string} s 숫자 문자열
* @return {number} 몇개의 문자열로 decoding 될 수 있는지
*/
const numDecodings = (s) => {
// 0으로 시작하는 경우는 decoding 불가능하므로 바로 예외 처리
if (s[0] === "0") return 0;
// 해당 숫자 문자열이 유효한지
const isValid = (ss) => {
const num = Number(ss);
return ss[0] !== "0" && 0 < num && num < 27;
};
// 문자열 길이가 1인 경우는 바로 유효성 검사로 return
// 아래에서 시작하는 인덱스가 2부터이기 때문에 미리 처리해야 함
const SIZE = s.length;
if (SIZE === 1) return isValid(s) ? 1 : 0;
// memoization 초기화
// base case인 첫 인덱스와 두번째 인덱스는 미리 계산해서 입력
// 배열로 하는 것이 정석이지만, 여기서는 구현 편의상 Object 활용
// 어차피 JS에서는 배열도 Object다..
const memo = {};
memo[SIZE - 1] = isValid(s[SIZE - 1]) ? 1 : 0;
memo[SIZE - 2] =
// 한자리 수 유효성 검사
(isValid(s[SIZE - 2]) ? memo[SIZE - 1] : 0) +
// 두자리 수 유효성 검사
(isValid(s[SIZE - 2] + s[SIZE - 1]) ? 1 : 0);
for (let i = SIZE - 3; i > -1; i--) {
let tmp = 0;
if (isValid(s[i])) tmp += memo[i + 1];
if (isValid(s[i] + s[i + 1])) tmp += memo[i + 2];
memo[i] = tmp;
}
return memo[0];
};
LeetCode 메모리 효율성 최상위 코드
var numDecodings = function(s) {
let memo = Array(s.length).fill(null);
return helper(s, 0, memo);
};
var helper = (s, start, memo) => {
if (start === s.length) return 1;
if (s[start] === '0') return 0;
if (start === s.length-1) return 1;
if (memo[start] !== null) return memo[start];
let result = helper(s, start+1, memo);
if (Number(s.slice(start, start+2)) <= 26) result += helper(s, start+2, memo)
memo[start] = result;
return result;
}