-
Notifications
You must be signed in to change notification settings - Fork 1
70. Climbing Stairs #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
abcbdc8
Add IntelliJ IDEA run configurations to gitignore and JUnit launcher …
yamcodes 5d18af7
Merge branch 'main' into 18-improve-minimum-deletions-space-complexit…
yamcodes 1fe4740
Add solution progression to package-info and stub O(1) DP solution
yamcodes 0ef02a2
Refactor solution links to use code tags for clarity
yamcodes 87750a9
Update solution progression to reflect new implementations
yamcodes d6a3ef0
Refactor solution progression documentation and add naive and prefix/…
yamcodes e00ba3d
Refactor: Rename solution classes and update references
yamcodes c874624
Refactor solution file naming and test structure
yamcodes 0ebe23f
Refactor Test run configuration encoding
yamcodes bebf22e
Rename test run configuration to "Test All"
yamcodes 808d20e
Implement space-optimized DP solution for minimum deletions
yamcodes dccc212
Refactor minimumDeletions to simplify logic and improve clarity
yamcodes 3022aaf
Refactor variable initialization for clarity
yamcodes 357059e
Disable unused test classes and reorder variables in Solution.java
yamcodes 4d737f4
Add TODO to refactor Solution with cleaner DP formulation
yamcodes ae5de78
Update TODO comment for DP implementation in minimum deletions
yamcodes 9916c30
Add climbing stairs solution and test cases
yamcodes d825814
Merge branch 'main' into climbing-stairs
yamcodes 6a031ed
Clarify `@ValueSource` and `@MethodSource` usage in README.md
yamcodes 7d0add9
Disable climbing stairs tests until implementation is complete
yamcodes 9ff2fde
Implement recursive solution for climbing stairs problem
yamcodes d910277
Implement memoized solution for climbing stairs problem
yamcodes bfb216e
Add base cases for n=1 and n=2 to memoized solution
yamcodes 9fc6b12
Initialize memoization array as a class member
yamcodes ab1871c
Implement dynamic programming solution for climbing stairs
yamcodes 5de63dd
Make Solution class public and adjust loop start index
yamcodes 2a6cb8a
Add Climbing Stairs to README
yamcodes f747d7e
Refactor Solution to O(1) space complexity
yamcodes File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| # Recursion to DP: Step by Step | ||
|
|
||
| ## Starting point: your memoized solution | ||
|
|
||
| ```java | ||
| int rec(int n) { | ||
| if (n == 1) return 1; | ||
| if (n == 2) return 2; | ||
| if (memo[n] != 0) return memo[n]; | ||
| memo[n] = rec(n - 1) + rec(n - 2); | ||
| return memo[n]; | ||
| } | ||
| ``` | ||
|
|
||
| ## Steps to convert to bottom-up DP | ||
|
|
||
| 1. **Look at what the memo array stores.** Each `memo[i]` holds the answer for input `i`. That's your DP table. | ||
|
|
||
| 2. **Find the base cases.** These are the entries you can fill without recursion: `memo[1] = 1` and `memo[2] = 2`. | ||
|
|
||
| 3. **Find the recurrence.** Strip away the recursion and just look at the formula: | ||
| `memo[n] = memo[n - 1] + memo[n - 2]`. | ||
|
|
||
| 4. **Figure out the fill order.** `memo[i]` depends on `memo[i - 1]` and `memo[i - 2]` — both smaller. So fill from | ||
| small to large (3, 4, 5, ... n). | ||
|
|
||
| 5. **Write the loop.** Seed the base cases, then loop from 3 to n applying the recurrence. | ||
|
|
||
| ## Result | ||
|
|
||
| ```java | ||
| int climbStairs(int n) { | ||
| if (n <= 2) return n; | ||
| int[] dp = new int[n + 1]; | ||
| dp[1] = 1; | ||
| dp[2] = 2; | ||
| for (int i = 3; i <= n; i++) { | ||
| dp[i] = dp[i - 1] + dp[i - 2]; | ||
| } | ||
| return dp[n]; | ||
| } | ||
| ``` | ||
|
|
||
| ## Bonus: space optimization | ||
|
|
||
| Notice `dp[i]` only ever reads `dp[i - 1]` and `dp[i - 2]`. You don't need the whole array — just two variables. | ||
|
|
||
| ```java | ||
| int climbStairs(int n) { | ||
| if (n <= 2) return n; | ||
| int prev2 = 1, prev1 = 2; | ||
| for (int i = 3; i <= n; i++) { | ||
| int curr = prev1 + prev2; | ||
| prev2 = prev1; | ||
| prev1 = curr; | ||
| } | ||
| return prev1; | ||
| } | ||
| ``` | ||
|
|
||
| This drops space from O(n) to O(1). |
27 changes: 27 additions & 0 deletions
27
src/main/java/codes/yam/leetcode/climbingstairs/Solution.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| /** | ||
| * Solution for the <b>Climbing Stairs</b> problem. | ||
| * | ||
| * <p>Optimizes {@code SolutionDp} by replacing the DP array with two rolling variables. | ||
| * | ||
| * <ul> | ||
| * <li><b>Time Complexity:</b> <code>O(n)</code> | ||
| * <li><b>Space Complexity:</b> <code>O(1)</code> | ||
| * </ul> | ||
| */ | ||
| class Solution { | ||
| int climbStairs(int n) { | ||
| if (n == 1) return 1; | ||
| if (n == 2) return 2; | ||
| int a = 1; | ||
| int b = 2; | ||
| int c = a + b; | ||
| for (int i = 3; i <= n; i++) { | ||
| c = a + b; | ||
| a = b; | ||
| b = c; | ||
| } | ||
| return c; | ||
| } | ||
| } |
22 changes: 22 additions & 0 deletions
22
src/main/java/codes/yam/leetcode/climbingstairs/SolutionDp.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| /** | ||
| * Solution for the <b>Climbing Stairs</b> problem. | ||
| * | ||
| * <ul> | ||
| * <li><b>Time Complexity:</b> <code>O(n)</code> | ||
| * <li><b>Space Complexity:</b> <code>O(n)</code> | ||
| * </ul> | ||
| */ | ||
| class SolutionDp { | ||
| int climbStairs(int n) { | ||
| if (n <= 2) return n; | ||
| int[] dp = new int[n + 1]; | ||
| dp[1] = 1; | ||
| dp[2] = 2; | ||
| for (int i = 3; i <= n; i++) { | ||
| dp[i] = dp[i - 1] + dp[i - 2]; | ||
| } | ||
| return dp[n]; | ||
| } | ||
| } | ||
27 changes: 27 additions & 0 deletions
27
src/main/java/codes/yam/leetcode/climbingstairs/SolutionMemoized.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| /** | ||
| * Solution for the <b>Climbing Stairs</b> problem. | ||
| * | ||
| * <ul> | ||
| * <li><b>Time Complexity:</b> <code>O(n)</code> | ||
| * <li><b>Space Complexity:</b> <code>O(n)</code> | ||
| * </ul> | ||
| */ | ||
| class SolutionMemoized { | ||
| int[] memo; | ||
|
|
||
| int rec(int n) { | ||
| if (n == 1) return 1; | ||
| if (n == 2) return 2; | ||
| if (memo[n] == 0) { | ||
| memo[n] = rec(n - 1) + rec(n - 2); | ||
| } | ||
| return memo[n]; | ||
| } | ||
|
|
||
| int climbStairs(int n) { | ||
| memo = new int[n + 1]; | ||
| return rec(n); | ||
| } | ||
| } |
17 changes: 17 additions & 0 deletions
17
src/main/java/codes/yam/leetcode/climbingstairs/SolutionRecursive.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| /** | ||
| * Solution for the <b>Climbing Stairs</b> problem. | ||
| * | ||
| * <ul> | ||
| * <li><b>Time Complexity:</b> <code>O(2^n)</code> | ||
| * <li><b>Space Complexity:</b> <code>O(n)</code> | ||
| * </ul> | ||
| */ | ||
| class SolutionRecursive { | ||
| int climbStairs(int n) { | ||
| if (n == 1) return 1; | ||
| if (n == 2) return 2; | ||
| return climbStairs(n - 1) + climbStairs(n - 2); | ||
| } | ||
| } |
14 changes: 14 additions & 0 deletions
14
src/test/java/codes/yam/leetcode/climbingstairs/SolutionDpTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
|
||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.MethodSource; | ||
|
|
||
| class SolutionDpTest { | ||
| @ParameterizedTest | ||
| @MethodSource("codes.yam.leetcode.climbingstairs.TestCases#cases") | ||
| void climbStairs(int n, int expected) { | ||
| assertEquals(expected, new SolutionDp().climbStairs(n)); | ||
| } | ||
| } |
14 changes: 14 additions & 0 deletions
14
src/test/java/codes/yam/leetcode/climbingstairs/SolutionMemoizedTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
|
||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.MethodSource; | ||
|
|
||
| class SolutionMemoizedTest { | ||
| @ParameterizedTest | ||
| @MethodSource("codes.yam.leetcode.climbingstairs.TestCases#cases") | ||
| void climbStairs(int n, int expected) { | ||
| assertEquals(expected, new SolutionMemoized().climbStairs(n)); | ||
| } | ||
| } |
14 changes: 14 additions & 0 deletions
14
src/test/java/codes/yam/leetcode/climbingstairs/SolutionRecursiveTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
|
||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.MethodSource; | ||
|
|
||
| class SolutionRecursiveTest { | ||
| @ParameterizedTest | ||
| @MethodSource("codes.yam.leetcode.climbingstairs.TestCases#cases") | ||
| void climbStairs(int n, int expected) { | ||
| assertEquals(expected, new SolutionRecursive().climbStairs(n)); | ||
| } | ||
| } |
14 changes: 14 additions & 0 deletions
14
src/test/java/codes/yam/leetcode/climbingstairs/SolutionTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
|
||
| import org.junit.jupiter.params.ParameterizedTest; | ||
| import org.junit.jupiter.params.provider.MethodSource; | ||
|
|
||
| class SolutionTest { | ||
| @ParameterizedTest | ||
| @MethodSource("codes.yam.leetcode.climbingstairs.TestCases#cases") | ||
| void climbStairs(int n, int expected) { | ||
| assertEquals(expected, new Solution().climbStairs(n)); | ||
| } | ||
| } |
11 changes: 11 additions & 0 deletions
11
src/test/java/codes/yam/leetcode/climbingstairs/TestCases.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package codes.yam.leetcode.climbingstairs; | ||
|
|
||
| import java.util.stream.Stream; | ||
| import org.junit.jupiter.params.provider.Arguments; | ||
|
|
||
| @SuppressWarnings("unused") | ||
| class TestCases { | ||
| static Stream<Arguments> cases() { | ||
| return Stream.of(Arguments.of(2, 2), Arguments.of(3, 3)); | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.