Skip to content

Commit d87ca7c

Browse files
authored
Refactor Unique Paths as requested in code review
1 parent ba22f9f commit d87ca7c

File tree

1 file changed

+79
-51
lines changed

1 file changed

+79
-51
lines changed

dynamic_programming/unique_paths.cpp

Lines changed: 79 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,74 +11,102 @@
1111
* @see https://leetcode.com/problems/unique-paths/
1212
*/
1313

14-
#include <iostream>
15-
#include <vector>
16-
#include <cassert>
17-
using namespace std;
14+
#include <iostream>
15+
#include <vector>
16+
#include <cassert>
1817

1918
/**
20-
* @namespace dp
19+
* @namespace dynamic_programming
2120
* @brief Dynamic Programming algorithms
2221
*/
23-
namespace dp {
22+
namespace dynamic_programming {
2423

2524
/**
26-
* @brief Recursive + Memoization solution.
27-
* @param i Current row index
28-
* @param j Current column index
29-
* @param m Number of rows
30-
* @param n Number of columns
31-
* @param dp Memoization table
32-
* @return int Number of unique paths from (i, j) to (m-1, n-1)
25+
* @class UniquePathsSolver
26+
* @brief Solves the Unique Paths problem using both memoization and tabulation.
3327
*/
34-
int solveMem(int i, int j, int m, int n, vector<vector<int>> &dp) {
35-
if (i >= m || j >= n) return 0;
36-
if (i == m - 1 && j == n - 1) return 1;
37-
if (dp[i][j] != -1) return dp[i][j];
38-
dp[i][j] = solveMem(i + 1, j, m, n, dp) + solveMem(i, j + 1, m, n, dp);
39-
return dp[i][j];
40-
}
28+
class UniquePathsSolver {
29+
private:
30+
std::vector<std::vector<int>> dp; ///< Memoization table
31+
int m, n;
4132

42-
/**
43-
* @brief Bottom-up Tabulation solution.
44-
* @param m Number of rows
45-
* @param n Number of columns
46-
* @return int Number of unique paths from (0, 0) to (m-1, n-1)
47-
*/
48-
int solveTab(int m, int n) {
49-
vector<vector<int>> dp(m, vector<int>(n, 0));
50-
for (int i = 0; i < m; i++) dp[i][n - 1] = 1; ///< last column paths = 1
51-
for (int j = 0; j < n; j++) dp[m - 1][j] = 1; ///< last row paths = 1
52-
for (int i = m - 2; i >= 0; i--) {
53-
for (int j = n - 2; j >= 0; j--) {
54-
dp[i][j] = dp[i + 1][j] + dp[i][j + 1]; ///< from down + right
33+
/**
34+
* @brief Recursive + Memoization solution.
35+
* @param i Current row index
36+
* @param j Current column index
37+
* @return int Number of unique paths from (i, j) to (m-1, n-1)
38+
*/
39+
int solveMem(int i, int j) {
40+
if (i >= m || j >= n) return 0;
41+
if (i == m - 1 && j == n - 1) return 1;
42+
if (dp.at(i).at(j) != -1) return dp.at(i).at(j);
43+
44+
dp.at(i).at(j) = solveMem(i + 1, j) + solveMem(i, j + 1);
45+
return dp.at(i).at(j);
46+
}
47+
48+
/**
49+
* @brief Bottom-up Tabulation solution.
50+
* @return int Number of unique paths from (0, 0) to (m-1, n-1)
51+
*/
52+
int solveTab() {
53+
std::vector<std::vector<int>> table(m, std::vector<int>(n, 0));
54+
55+
for (int i = 0; i < m; i++) table[i][n - 1] = 1; ///< last column
56+
for (int j = 0; j < n; j++) table[m - 1][j] = 1; ///< last row
57+
58+
for (int i = m - 2; i >= 0; i--) {
59+
for (int j = n - 2; j >= 0; j--) {
60+
table[i][j] = table[i + 1][j] + table[i][j + 1];
61+
}
5562
}
63+
return table[0][0];
5664
}
57-
return dp[0][0];
58-
}
5965

60-
/**
61-
* @brief Returns number of unique paths in an m x n grid.
62-
* @param m Number of rows
63-
* @param n Number of columns
64-
* @return int Total number of unique paths
65-
*/
66-
int uniquePaths(int m, int n) {
67-
vector<vector<int>> dp(m + 1, vector<int>(n + 1, -1));
68-
// return solveMem(0, 0, m, n, dp);
69-
return solveTab(m, n);
66+
public:
67+
/**
68+
* @brief Constructor initializes dimensions and memo table
69+
*/
70+
UniquePathsSolver(int rows, int cols) : m(rows), n(cols) {
71+
dp.assign(m, std::vector<int>(n, -1));
72+
}
73+
74+
/**
75+
* @brief Get number of unique paths using Memoization
76+
*/
77+
int uniquePathsMemo() { return solveMem(0, 0); }
7078

71-
} // namespace dp
79+
/**
80+
* @brief Get number of unique paths using Tabulation
81+
*/
82+
int uniquePathsTab() { return solveTab(); }
83+
};
84+
85+
} // namespace dynamic_programming
7286

7387
/**
7488
* @brief Self-test implementations
7589
*/
7690
static void test() {
77-
assert(dp::uniquePaths(3, 7) == 28);
78-
assert(dp::uniquePaths(3, 2) == 3);
79-
assert(dp::uniquePaths(1, 1) == 1);
80-
assert(dp::uniquePaths(2, 2) == 2);
81-
cout << "All tests have successfully passed!\n";
91+
using namespace dynamic_programming;
92+
93+
UniquePathsSolver solver1(3, 7);
94+
assert(solver1.uniquePathsMemo() == 28);
95+
assert(solver1.uniquePathsTab() == 28);
96+
97+
UniquePathsSolver solver2(3, 2);
98+
assert(solver2.uniquePathsMemo() == 3);
99+
assert(solver2.uniquePathsTab() == 3);
100+
101+
UniquePathsSolver solver3(1, 1);
102+
assert(solver3.uniquePathsMemo() == 1);
103+
assert(solver3.uniquePathsTab() == 1);
104+
105+
UniquePathsSolver solver4(2, 2);
106+
assert(solver4.uniquePathsMemo() == 2);
107+
assert(solver4.uniquePathsTab() == 2);
108+
109+
std::cout << "All tests have successfully passed!\n";
82110
}
83111

84112
/**

0 commit comments

Comments
 (0)