예로 들어서 n이 3이라면 꼭대기에 도달 하는데까지 총 3가지의 방법이 존재한다.
다른 예시로는
n = 1
// 한 가지의 방법만 존재하므로 1을 출력
n = 2
// 2, (1 , 1)과 (2)
n = 4
// 5, (1, 1, 1, 1), (1, 1, 2), (2, 1, 1), (1, 2, 1), (2, 2)
재귀를 사용한 방식
방법의 수(n) = 방법의 수(n - 1) + 방법의 수(n - 2)
피보나치 수열을 이용하여 구할 수가 있다.
방법의 수(1) = 피보나치(2) = 1
방법의 수(2) = 피보나치(3) = 2
방법의 수(3) = 피보나치(4) = 3
int fib(int n)
{
if (n <= 1)
return n;
return fib(n - 1) + fib(n - 2);
}
int countWays(int s) { return fib(s + 1); }
int main()
{
int s = 4;
cout << "Number of ways = " << countWays(s);
return 0;
}
시간 / 공간 복잡도
시간) O(2 n제곱) 2개의 선택지가 주어졌고 n개의 계단 수
공간) O(n) 재귀 스택메모리 공간이 필요
DP (메모이제이션 / 업다운) - 시간 / 공간 복잡도 O(n)
- 목표지점 n에 도달할 수 있는 방법인 1차원 배열인 dp[i]를 생성한다.
- 이전에 값을 구했는지 확인한다.
- 재귀해서 이전 값들의 결과를 저장한다. 예) dp[n] = 방법의 수(n - 1, dp) + 방법의 수(n - 2, dp)
- 결과는 dp[n]이다.
int countWays(int n, int dp[])
{
if (n <= 1)
return dp[n] = 1;
if (dp[n] != -1) {
return dp[n];
}
dp[n] = countWays(n - 1, dp) + countWays(n - 2, dp);
return dp[n];
}
int main()
{
int n = 4;
int dp[n + 1];
memset(dp, -1, sizeof dp);
cout << "Number of ways = " << countWays(n, dp);
return 0;
}
DP (바텀업) - 시간 / 공간 복잡도 O(n)
다음과 같은 관계로 dp를 생선한다
dp[i] = dp[i-1] + dp[i-2]
- 1차원 배열 (dp)을 생성한다.
- 2는 2가지의 방법이 존재하므로 dp[0]이랑 dp[1]을 1로 초기화한다.
// C++ program to count number of ways
// to reach n'th stair when a person
// can climb 1, 2, ..m stairs at a time
#include <iostream>
using namespace std;
// A function to find number of ways to reach the nth stair
int countWays(int n)
{
vector<int> dp(n + 1);
dp[0] = dp[1] = 1;
for (int i = 2; i <= n; i++)
dp[i] = dp[i - 1] + dp[i - 2];
return dp[n];
}
// Driver code
int main()
{
int n = 4;
cout << "Number of ways = " << countWays(n);
return 0;
}
'CS > 자료구조 & 알고리즘' 카테고리의 다른 글
[C++] 라운드 로빈 스케줄링 구현 (우선순위 큐 이용) (0) | 2024.03.06 |
---|---|
[C++] lower bound, upper bound (0) | 2023.12.19 |
sort() 함수에서 쓰여지는 정렬 알고리즘 (Intro 인트로, Tim 팀) (0) | 2023.12.11 |
[C++] Radix Sort (기수 정렬) (0) | 2023.12.04 |
[C++] Trie (트라이) 소스코드 (0) | 2023.12.01 |