Algorithm
[Toy] 6 - 10
heesue
2021. 5. 5. 15:13
6. sudoku
일부 칸이 비어있는(0이 입력된) 상태의 스도쿠 보드를 입력받아 완성된 보드를 리턴
(board는 가로 길이와 세로 길이가 모두 9인 2차원 배열이다.)
const sudoku = function (board) {
const N = board.length; // N = 9
const boxes = [
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[3, 3, 3, 4, 4, 4, 5, 5, 5],
[3, 3, 3, 4, 4, 4, 5, 5, 5],
[3, 3, 3, 4, 4, 4, 5, 5, 5],
[6, 6, 6, 7, 7, 7, 8, 8, 8],
[6, 6, 6, 7, 7, 7, 8, 8, 8],
[6, 6, 6, 7, 7, 7, 8, 8, 8],
];
const getBoxNum = (row, col) => boxes[row][col];
const blanks = [];
const rowUsed = [];
const colUsed = [];
const boxUsed = [];
for (let row = 0; row < N; row++) {
rowUsed.push(Array(N + 1).fill(false));
colUsed.push(Array(N + 1).fill(false));
boxUsed.push(Array(N + 1).fill(false));
}
for (let row = 0; row < N; row++) {
for (let col = 0; col < N; col++) {
if (board[row][col] === 0) {
blanks.push([row, col]);
} else {
const num = board[row][col];
const box = getBoxNum(row, col);
rowUsed[row][num] = true;
colUsed[col][num] = true;
boxUsed[box][num] = true;
}
}
}
const isValid = (row, col, num) => {
const box = getBoxNum(row, col);
return (
rowUsed[row][num] === false &&
colUsed[col][num] === false &&
boxUsed[box][num] === false
);
};
const toggleNum = (row, col, num) => {
const box = getBoxNum(row, col);
board[row][col] = num;
rowUsed[row][num] = !rowUsed[row][num];
colUsed[col][num] = !colUsed[col][num];
boxUsed[box][num] = !boxUsed[box][num];
};
const aux = (idx, blanks, board) => {
if (idx === blanks.length) {
return true;
}
const [row, col] = blanks[idx];
for (let num = 1; num <= 9; num++) {
if (isValid(row, col, num) === true) {
toggleNum(row, col, num);
if (aux(idx + 1, blanks, board) === true) {
return true;
}
toggleNum(row, col, num);
}
}
return false;
};
aux(0, blanks, board);
return board;
};
7. treeDFS
임의의 tree를 구성하는 노드 중 하나의 Node 객체를 입력받아, 해당 노드를 시작으로 깊이 우선 탐색(DFS, Depth First Search)을 하여 탐색되는 순서대로 노드의 값이 저장된 배열을 리턴
let dfs = function (node) {
let values = [node.value];
node.children.forEach((n) => {
values = values.concat(dfs(n)); // 재귀 이용
});
return values;
};
// 이 아래 코드는 변경 X
let Node = function (value) {
this.value = value;
this.children = [];
};
// 위 Node 객체로 구성되는 트리는 매우 단순한 형태의 트리이다.
// membership check(중복 확인)를 따로 하지 않는다.
Node.prototype.addChild = function (child) {
this.children.push(child);
return child;
};
8. largestProductOfThree
정수를 요소로 갖는 배열을 입력받아 3개의 요소를 곱해 나올 수 있는 최대값을 리턴
(단, 배열은 1차원 배열이며 음수와 0을 포함하고, 배열의 길이는 3 이상이다.)
const largestProductOfThree = function (arr) {
const sorted = arr.slice().sort((a, b) => a - b);
const len = arr.length;
const case1 = sorted[len - 1] * sorted[len - 2] * sorted[len - 3];
const case2 = sorted[len - 1] * sorted[0] * sorted[1];
return Math.max(case1, case2);
};
9. power => 디버깅☆
두 수를 입력받아 거듭제곱을 리턴 (단, Math.pow와 거듭제곱 연산자를 사용하지 않는다.)
=> 실제 계산 결과를 94,906,249로 나눈 나머지를 리턴해야 한다. 계산 결과가 컴퓨터로 나타낼 수 있는 범위를 넘을 수 있기 때문에 나머지를 구해야 한다. 이때, 연산 중간에도 이 범위를 넘을 수 있으므로 모든 연산이 끝난 결과에서 나머지를 구하는 것이 아니라 연산할 때마다 나머지를 구하고 연산을 이어가야 한다.
function power(base, exponent) {
if (exponent === 0) return 1;
const half = parseInt(exponent / 2);
const temp = power(base, half);
const result = (temp * temp) % 94906249;
if (exponent % 2 === 1) {
return (base * result) % 94906249;
} else {
return result;
}
}
10. binarySearch => 이진탐색 (O(logN))
오름차순 정렬된 정수의 배열(arr)과 정수(target)를 입력받아 target의 인덱스를 리턴 (단, target이 없으면 -1을 리턴)
const binarySearch = function (arr, target) {
let start = 0;
let end = arr.length - 1;
while (start <= end) {
let mid = parseInt((start + end) / 2);
if (arr[mid] === target) {
return mid;
} else if (arr[mid] < target) {
start = mid + 1;
} else {
end = mid - 1;
}
} return -1;
}