-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclimbing_stairs.cpp
More file actions
116 lines (99 loc) · 2.73 KB
/
Copy pathclimbing_stairs.cpp
File metadata and controls
116 lines (99 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
* Task: Count the number of ways to climb N steps with allowed step sizes.
*
* CLIMBING STAIRS WITH CUSTOM STEPS
*
* Problem:
* Given an integer N and a list of allowed step sizes, return the number of
* distinct ordered ways to reach exactly step N.
*
* Constraints:
* - 0 <= N <= 1000
* - 1 <= allowedSteps.size() <= 10
* - Each allowed step is a positive integer.
*
* Example:
* Input: N = 5, allowedSteps = [1,2]
* Output: 8
*/
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
// Simple (Recursive) Solution
// Complexity: O(N^M) where M is size of allowedSteps
int simpleSolution(int N, const std::vector<int> &allowedSteps) {
if (N == 0)
return 1;
if (N < 0)
return 0;
int totalWays = 0;
for (int step : allowedSteps) {
totalWays += simpleSolution(N - step, allowedSteps);
}
return totalWays;
}
// Optimal (Dynamic Programming) Solution
// Complexity: O(N * M)
int optimalSolution(int N, const std::vector<int> &allowedSteps) {
std::vector<int> dp(N + 1, 0);
dp[0] = 1;
for (int i = 1; i <= N; ++i) {
for (int step : allowedSteps) {
if (i - step >= 0)
dp[i] += dp[i - step];
}
}
return dp[N];
}
namespace {
struct TestRunner {
int total = 0;
int failed = 0;
void expectEqual(int got, int expected, const std::string &label) {
++total;
if (got == expected) {
std::cout << "[PASS] " << label << "\n";
return;
}
++failed;
std::cout << "[FAIL] " << label << " expected=" << expected
<< " got=" << got << "\n";
}
void summary() const {
std::cout << "Tests: " << total - failed << " passed, " << failed
<< " failed, " << total << " total\n";
}
};
} // namespace
// Test cases for correctness
void test() {
struct TestCase {
int N;
std::vector<int> allowedSteps;
int expected;
};
std::vector<TestCase> tests = {{4, {1, 3}, 3},
{5, {1, 2}, 8},
{3, {2}, 0},
{7, {1, 3, 5}, 12},
{10, {2, 5}, 2}};
TestRunner runner;
for (const auto &test : tests) {
int simple = simpleSolution(test.N, test.allowedSteps);
int optimal = optimalSolution(test.N, test.allowedSteps);
runner.expectEqual(simple, optimal,
"simple == optimal for N=" + std::to_string(test.N));
runner.expectEqual(optimal, test.expected,
"expected ways for N=" + std::to_string(test.N));
std::cout << "Stairs: " << test.N << " | Allowed Steps: ";
for (int s : test.allowedSteps)
std::cout << s << " ";
std::cout << "| Ways: " << optimal << std::endl;
}
runner.summary();
}
int main() {
test();
return 0;
}