재귀란 무엇인가
function recursion() {
console.log("here");
recursion();
}
recursion() // 무한 루프
function recursion(count) {
if (count < 0) return // 반복을 멈출 조건을 설정
console.log("here", count);
recursion(count - 1); // 인수 업데이트 및 재귀 함수 호출
}
let count = 4;
recursion(count)
function recursion(count) {
if (count < 0) return // base case
// 적어도 하나의 recursion에 빠지지 않는 경우가 존재해야 함
console.log("here", count);
recursion(count - 1); // Recursive case
// recursion을 반복하다보면 결국 base case로 수렴해야 함.
}
let count = 4;
recursion(count)
- 적어도 하나의 recursion에 빠지지 않는 경우가 존재해야 함
- recursion을 반복하다보면 결국 base case로 수렴해야 함
1~n
까지의 합 구하기// 이 함수의 mission은 0~n까지의 합을 구하는 것
function recursion(num) {
if (num === 0) {
// n=0이라면 합은 0
return 0
} else {
// n이 0보다 크다면 0에서 n까지의 합은 0에서 n-1까지의 합에 n을 더한 값
return num + recursion(num - 1);
}
}
let num = 4;
recursion(num)
function factorial(n) {
if (n === 0) {
return 1
} else {
return n * factorial(n - 1)
}
}
let n = 4;
factorial(n)
function power(num, n) {
if (n === 0) {
return 1
} else {
return num * power(num, n - 1)
}
}
const num = 2
const n = 4;
power(num, n)
function fibonacci(n) {
if (n < 2) {
return n
} else {
return fibonacci(n - 1) + fibonacci(n - 2)
}
}
const n = 4;
fibonacci(n)
function gcd(a, b) {
if (a < b) {
let temp = a
a = b
b = temp
}
if (a % b === 0) {
return b
} else {
return gcd(b, a % b)
}
}
const a = 12;
const b = 8;
gcd(a, b)
function gcd(a, b) {
if (b === 0) {
return a
} else {
return gcd(b, a % b)
}
}
const a = 8;
const b = 12;
gcd(a, b)
순환적으로 사고하기
function strLength(str) {
if (!str) {
return 0
} else {
return 1 + strLength(str.substring(1))
}
}
const str = "Hello world!"
strLength(str)
function printChars(str) {
if (!str) {
return;
} else {
console.log(str.charAt(0))
printChars(str.substring(1))
}
}
const str = "Hello world!"
printChars(str)
function printCharsReverse(str) {
if (!str) {
return;
} else {
printCharsReverse(str.substring(1))
console.log(str.charAt())
}
}
const str = "Hello world!"
printCharsReverse(str)
function printInBinary(n) {
if (n < 2) {
console.log(n);
} else {
printInBinary(Math.floor(n / 2))
console.log(n % 2);
}
}
const n = 10;
printInBinary(n)
function arraySum(n, arr) {
if (n <= 0) {
return 0;
} else {
console.log(arr[n - 1]);
return arr[n - 1] + arraySum(n - 1, arr)
}
}
const n = 10;
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arraySum(n, arr);
재귀 vs 반복
순환 알고리즘의 설계
무한루프에 빠지지 않는 재귀함수의 전제 조건
- 적어도 하나의 recursion에 빠지지 않는 경우가 존재해야 함
- recursion을 반복하다보면 결국 base case로 수렴해야 함
암시적(implicit) 매개변수를
명시적(explicit) 매개변수로 바꾸어라.
function search(arr, n, target) {
for (let i = 0; i < n; i++) {
if (arr[i] === target) {
return i
}
}
return -1
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const n = 7
const target = 5
console.log(search(arr, n, target));
function search(arr, begin, end, target) {
if (begin > end) {
return -1;
} else if (target === arr[begin]) {
return begin
} else {
return search(arr, begin + 1, end, target)
}
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const begin = 0
const end = 7
const target = 5
console.log(search(arr, begin, end, target))
즉, 재귀함수를 구현할 때 처음 함수를 실행하는 경우뿐만 아니라 두번째, 세번째 실행할 때의 매개변수를 염두해두고 설계를 해야함
function search(arr, begin, end, target) {
if (begin > end) {
return -1;
} else if (target === arr[end]) {
return end
} else {
return search(arr, begin, end - 1, target)
}
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const begin = 0
const end = 7
const target = 5
console.log(search(arr, begin, end, target));
function search(arr, begin, end, target) {
if (begin > end) {
return -1;
} else {
let mid = Math.floor((begin + end) / 2)
if (arr[mid] === target) {
return mid
}
let index = search(arr, begin, mid - 1, target)
if (index !== -1) {
return index
} else {
return search(arr, mid + 1, end, target)
}
}
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const begin = 0
const end = 7
const target = 5
console.log(search(arr, begin, end, target));
function findMax(arr) {
let max = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i]
}
}
return max
}
const arr = [1, 2, 5, 6, 4, 7, 9, 8, 3]
console.log(findMax(arr));
function findMax(index, arr) {
if (index === arr.length-1) {
return arr[index]
} else {
return Math.max(arr[index], findMax(index + 1, arr))
}
}
const arr = [1, 2, 5, 6, 4, 7, 9, 8, 3]
console.log(searchMaxValue(0, arr));
function findMax(begin, end, arr) {
if (begin === end) {
return arr[begin]
} else {
let mid = Math.floor((begin + end) / 2)
let max1 = findMax(begin, mid, arr)
let max2 = findMax(mid + 1, end, arr)
return Math.max(max1, max2)
}
}
const arr = [1, 2, 5, 6, 4, 7, 9, 8, 3]
const end = arr.length - 1
console.log(findMax(0, end, arr));
function binarySearch(arr, target, begin, end) {
if (begin > end) {
return -1
} else {
let mid = Math.floor((begin + end) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] > target) {
return binarySearch(arr, target, begin, mid - 1)
} else {
return binarySearch(arr, target, mid + 1, end)
}
}
}
//if arr가 정렬되어 있지 않다면, arr.sort() 필요
const arr = [1, 2, 4, 9, 13, 15, 20, 22, 30, 40, 50, 60, 77, 100];
const target = 77;
const begin = 0;
const end = arr.length - 1;
console.log(binarySearch(arr, target, begin, end));
YOUTUBE | 2015 봄학기 알고리즘 | 권오흠
모던 JavaScript 튜토리얼 | 재귀와 스택
Photo by Michael Dziedzic on Unsplash