From 73f3702e6a2203a9f720cf01943b153352f7681e Mon Sep 17 00:00:00 2001 From: Sri Hari Date: Fri, 18 Oct 2024 06:34:38 +0530 Subject: [PATCH] Batch-2/Neetcode-150/articles --- articles/climbing-stairs.md | 646 +++++++++++++++++++++ articles/house-robber-ii.md | 524 +++++++++++++++++ articles/house-robber.md | 421 ++++++++++++++ articles/longest-palindromic-substring.md | 670 ++++++++++++++++++++++ articles/min-cost-climbing-stairs.md | 381 ++++++++++++ 5 files changed, 2642 insertions(+) create mode 100644 articles/climbing-stairs.md create mode 100644 articles/house-robber-ii.md create mode 100644 articles/house-robber.md create mode 100644 articles/longest-palindromic-substring.md create mode 100644 articles/min-cost-climbing-stairs.md diff --git a/articles/climbing-stairs.md b/articles/climbing-stairs.md new file mode 100644 index 000000000..e6677b0d5 --- /dev/null +++ b/articles/climbing-stairs.md @@ -0,0 +1,646 @@ +## 1. Recursion + +::tabs-start + +```python +class Solution: + def climbStairs(self, n: int) -> int: + + def dfs(i): + if i >= n: + return i == n + return dfs(i + 1) + dfs(i + 2) + + return dfs(0) +``` + +```java +public class Solution { + public int climbStairs(int n) { + return dfs(n, 0); + } + + public int dfs(int n, int i) { + if (i >= n) return i == n ? 1 : 0; + return dfs(n, i + 1) + dfs(n, i + 2); + } +} +``` + +```cpp +class Solution { +public: + int climbStairs(int n) { + return dfs(n, 0); + } + + int dfs(int n, int i) { + if (i >= n) return i == n; + return dfs(n, i + 1) + dfs(n, i + 2); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} n + * @return {number} + */ + climbStairs(n) { + + const dfs = (i) => { + if (i >= n) return i == n; + return dfs(i + 1) + dfs(i + 2); + } + return dfs(0); + } +} +``` + +```csharp +public class Solution { + public int ClimbStairs(int n) { + return Dfs(n, 0); + } + + public int Dfs(int n, int i) { + if (i >= n) return i == n ? 1 : 0; + return Dfs(n, i + 1) + Dfs(n, i + 2); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(2 ^ n)$ +* Space complexity: $O(n)$ + +--- + +## 2. DP (Memoization) + +::tabs-start + +```python +class Solution: + def climbStairs(self, n: int) -> int: + cache = [-1] * n + def dfs(i): + if i >= n: + return i == n + if cache[i] != -1: + return cache[i] + cache[i] = dfs(i + 1) + dfs(i + 2) + return cache[i] + + return dfs(0) +``` + +```java +public class Solution { + int[] cache; + public int climbStairs(int n) { + cache = new int[n]; + for (int i = 0; i < n; i++) { + cache[i] = -1; + } + return dfs(n, 0); + } + + public int dfs(int n, int i) { + if (i >= n) return i == n ? 1 : 0; + if (cache[i] != -1) return cache[i]; + return cache[i] = dfs(n, i + 1) + dfs(n, i + 2); + } +} +``` + +```cpp +class Solution { +public: + vector cache; + int climbStairs(int n) { + cache.resize(n, -1); + return dfs(n, 0); + } + + int dfs(int n, int i) { + if (i >= n) return i == n; + if (cache[i] != -1) return cache[i]; + return cache[i] = dfs(n, i + 1) + dfs(n, i + 2); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} n + * @return {number} + */ + climbStairs(n) { + const cache = new Int32Array(n).fill(-1); + const dfs = (i) => { + if (i >= n) return i == n; + if (cache[i] != -1) return cache[i]; + return cache[i] = dfs(i + 1) + dfs(i + 2); + } + return dfs(0); + } +} +``` + +```csharp +public class Solution { + int[] cache; + public int ClimbStairs(int n) { + cache = new int[n]; + for (int i = 0; i < n; i++) { + cache[i] = -1; + } + return Dfs(n, 0); + } + + public int Dfs(int n, int i) { + if (i >= n) return i == n ? 1 : 0; + if (cache[i] != -1) return cache[i]; + return cache[i] = Dfs(n, i + 1) + Dfs(n, i + 2); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. DP (Tabulation) + +::tabs-start + +```python +class Solution: + def climbStairs(self, n: int) -> int: + if n <= 2: + return n + dp = [0] * (n + 1) + dp[1], dp[2] = 1, 2 + for i in range(3, n + 1): + dp[i] = dp[i - 1] + dp[i - 2] + return dp[n] +``` + +```java +public class Solution { + public 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]; + } +} +``` + +```cpp +class Solution { +public: + int climbStairs(int n) { + if (n <= 2) { + return n; + } + vector dp(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]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} n + * @return {number} + */ + climbStairs(n) { + if (n <= 2) { + return n; + } + let dp = new Array(n + 1).fill(0); + dp[1] = 1; + dp[2] = 2; + for (let i = 3; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + return dp[n]; + } +} +``` + +```csharp +public class Solution { + public 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]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. DP (Space Optimized) + +::tabs-start + +```python +class Solution: + def climbStairs(self, n: int) -> int: + one, two = 1, 1 + + for i in range(n - 1): + temp = one + one = one + two + two = temp + + return one +``` + +```java +public class Solution { + public int climbStairs(int n) { + int one = 1, two = 1; + + for (int i = 0; i < n - 1; i++) { + int temp = one; + one = one + two; + two = temp; + } + + return one; + } +} +``` + +```cpp +class Solution { +public: + int climbStairs(int n) { + int one = 1, two = 1; + + for (int i = 0; i < n - 1; i++) { + int temp = one; + one = one + two; + two = temp; + } + + return one; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} n + * @return {number} + */ + climbStairs(n) { + let one = 1, two = 1; + + for (let i = 0; i < n - 1; i++) { + let temp = one; + one = one + two; + two = temp; + } + + return one; + } +} +``` + +```csharp +public class Solution { + public int ClimbStairs(int n) { + int one = 1, two = 1; + + for (int i = 0; i < n - 1; i++) { + int temp = one; + one = one + two; + two = temp; + } + + return one; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ + +--- + +## 5. Matrix Exponentiation + +::tabs-start + +```python +class Solution: + def climbStairs(self, n: int) -> int: + if n == 1: + return 1 + + def matrix_mult(A, B): + return [[A[0][0] * B[0][0] + A[0][1] * B[1][0], + A[0][0] * B[0][1] + A[0][1] * B[1][1]], + [A[1][0] * B[0][0] + A[1][1] * B[1][0], + A[1][0] * B[0][1] + A[1][1] * B[1][1]]] + + def matrix_pow(M, p): + result = [[1, 0], [0, 1]] + base = M + + while p: + if p % 2 == 1: + result = matrix_mult(result, base) + base = matrix_mult(base, base) + p //= 2 + + return result + + M = [[1, 1], [1, 0]] + result = matrix_pow(M, n) + return result[0][0] +``` + +```java +public class Solution { + public int climbStairs(int n) { + if (n == 1) return 1; + + int[][] M = {{1, 1}, {1, 0}}; + int[][] result = matrixPow(M, n); + + return result[0][0]; + } + + private int[][] matrixMult(int[][] A, int[][] B) { + return new int[][] { + {A[0][0] * B[0][0] + A[0][1] * B[1][0], + A[0][0] * B[0][1] + A[0][1] * B[1][1]}, + {A[1][0] * B[0][0] + A[1][1] * B[1][0], + A[1][0] * B[0][1] + A[1][1] * B[1][1]} + }; + } + + private int[][] matrixPow(int[][] M, int p) { + int[][] result = {{1, 0}, {0, 1}}; + int[][] base = M; + + while (p > 0) { + if (p % 2 == 1) { + result = matrixMult(result, base); + } + base = matrixMult(base, base); + p /= 2; + } + + return result; + } +} +``` + +```cpp +class Solution { +public: + int climbStairs(int n) { + if (n == 1) return 1; + + vector> M = {{1, 1}, {1, 0}}; + vector> result = matrixPow(M, n); + + return result[0][0]; + } + +private: + vector> matrixMult(vector>& A, vector>& B) { + return {{A[0][0] * B[0][0] + A[0][1] * B[1][0], + A[0][0] * B[0][1] + A[0][1] * B[1][1]}, + {A[1][0] * B[0][0] + A[1][1] * B[1][0], + A[1][0] * B[0][1] + A[1][1] * B[1][1]}}; + } + + vector> matrixPow(vector>& M, int p) { + vector> result = {{1, 0}, {0, 1}}; + vector> base = M; + + while (p > 0) { + if (p % 2 == 1) { + result = matrixMult(result, base); + } + base = matrixMult(base, base); + p /= 2; + } + + return result; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} n + * @return {number} + */ + climbStairs(n) { + if (n === 1) return 1; + + const matrixMult = (A, B) => { + return [ + [A[0][0] * B[0][0] + A[0][1] * B[1][0], + A[0][0] * B[0][1] + A[0][1] * B[1][1]], + [A[1][0] * B[0][0] + A[1][1] * B[1][0], + A[1][0] * B[0][1] + A[1][1] * B[1][1]] + ]; + }; + + const matrixPow = (M, p) => { + let result = [[1, 0], [0, 1]]; + let base = M; + + while (p > 0) { + if (p % 2 === 1) { + result = matrixMult(result, base); + } + base = matrixMult(base, base); + p = Math.floor(p / 2); + } + + return result; + }; + + const M = [[1, 1], [1, 0]]; + const result = matrixPow(M, n); + + return result[0][0]; + } +} +``` + +```csharp +public class Solution { + public int ClimbStairs(int n) { + if (n == 1) return 1; + + int[,] M = new int[,] {{1, 1}, {1, 0}}; + int[,] result = MatrixPow(M, n); + + return result[0, 0]; + } + + private int[,] MatrixMult(int[,] A, int[,] B) { + return new int[,] { + {A[0, 0] * B[0, 0] + A[0, 1] * B[1, 0], + A[0, 0] * B[0, 1] + A[0, 1] * B[1, 1]}, + {A[1, 0] * B[0, 0] + A[1, 1] * B[1, 0], + A[1, 0] * B[0, 1] + A[1, 1] * B[1, 1]} + }; + } + + private int[,] MatrixPow(int[,] M, int p) { + int[,] result = new int[,] {{1, 0}, {0, 1}}; + int[,] baseM = M; + + while (p > 0) { + if (p % 2 == 1) { + result = MatrixMult(result, baseM); + } + baseM = MatrixMult(baseM, baseM); + p /= 2; + } + + return result; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(\log n)$ +* Space complexity: $O(1)$ + +--- + +## 6. Math + +::tabs-start + +```python +class Solution: + def climbStairs(self, n: int) -> int: + sqrt5 = math.sqrt(5) + phi = (1 + sqrt5) / 2 + psi = (1 - sqrt5) / 2 + n += 1 + return round((phi**n - psi**n) / sqrt5) +``` + +```java +public class Solution { + public int climbStairs(int n) { + double sqrt5 = Math.sqrt(5); + double phi = (1 + sqrt5) / 2; + double psi = (1 - sqrt5) / 2; + n++; + return (int) Math.round((Math.pow(phi, n) - + Math.pow(psi, n)) / sqrt5); + } +} +``` + +```cpp +class Solution { +public: + int climbStairs(int n) { + double sqrt5 = sqrt(5); + double phi = (1 + sqrt5) / 2; + double psi = (1 - sqrt5) / 2; + n++; + return round((pow(phi, n) - pow(psi, n)) / sqrt5); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number} n + * @return {number} + */ + climbStairs(n) { + let sqrt5 = Math.sqrt(5); + let phi = (1 + sqrt5) / 2; + let psi = (1 - sqrt5) / 2; + n++; + return Math.round((Math.pow(phi, n) - + Math.pow(psi, n)) / sqrt5); + } +} +``` + +```csharp +public class Solution { + public int ClimbStairs(int n) { + double sqrt5 = Math.Sqrt(5); + double phi = (1 + sqrt5) / 2; + double psi = (1 - sqrt5) / 2; + n++; + return (int) Math.Round((Math.Pow(phi, n) - + Math.Pow(psi, n)) / sqrt5); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(\log n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/house-robber-ii.md b/articles/house-robber-ii.md new file mode 100644 index 000000000..b52b97b39 --- /dev/null +++ b/articles/house-robber-ii.md @@ -0,0 +1,524 @@ +## 1. Recursion + +::tabs-start + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + if len(nums) == 1: + return nums[0] + def dfs(i, flag): + if i >= len(nums) or (flag and i == len(nums) - 1): + return 0 + + return max(dfs(i + 1, flag), + nums[i] + dfs(i + 2, flag or i == 0)) + return max(dfs(0, True), dfs(1, False)) +``` + +```java +public class Solution { + public int rob(int[] nums) { + if (nums.length == 1) return nums[0]; + return Math.max(dfs(0, true, nums), dfs(1, false, nums)); + } + + private int dfs(int i, boolean flag, int[] nums) { + if (i >= nums.length || (flag && i == nums.length - 1)) + return 0; + + return Math.max(dfs(i + 1, flag, nums), + nums[i] + dfs(i + 2, flag || i == 0, nums)); + } +} +``` + +```cpp +class Solution { +public: + int rob(vector& nums) { + if (nums.size() == 1) return nums[0]; + return max(dfs(0, true, nums), dfs(1, false, nums)); + } + +private: + int dfs(int i, bool flag, vector& nums) { + if (i >= nums.size() || (flag && i == nums.size() - 1)) + return 0; + + return max(dfs(i + 1, flag, nums), + nums[i] + dfs(i + 2, flag || i == 0, nums)); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + if (nums.length === 1) return nums[0]; + + const dfs = (i, flag) => { + if (i >= nums.length || (flag && i === nums.length - 1)) + return 0; + + return Math.max(dfs(i + 1, flag), + nums[i] + dfs(i + 2, flag || i === 0)); + } + + return Math.max(dfs(0, true), dfs(1, false)); + } +} +``` + +```csharp +public class Solution { + public int Rob(int[] nums) { + if (nums.Length == 1) return nums[0]; + return Math.Max(Dfs(0, true, nums), Dfs(1, false, nums)); + } + + private int Dfs(int i, bool flag, int[] nums) { + if (i >= nums.Length || (flag && i == nums.Length - 1)) + return 0; + + return Math.Max(Dfs(i + 1, flag, nums), + nums[i] + Dfs(i + 2, flag || i == 0, nums)); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(2 ^ n)$ +* Space complexity: $O(n)$ + +--- + +## 2. DP (Memoization) + +::tabs-start + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + if len(nums) == 1: + return nums[0] + + memo = [[-1] * 2 for _ in range(len(nums))] + + def dfs(i, flag): + if i >= len(nums) or (flag and i == len(nums) - 1): + return 0 + if memo[i][flag] != -1: + return memo[i][flag] + memo[i][flag] = max(dfs(i + 1, flag), + nums[i] + dfs(i + 2, flag or (i == 0))) + return memo[i][flag] + + return max(dfs(0, True), dfs(1, False)) +``` + +```java +public class Solution { + private int[][] memo; + + public int rob(int[] nums) { + if (nums.length == 1) return nums[0]; + + memo = new int[nums.length][2]; + for (int i = 0; i < nums.length; i++) { + memo[i][0] = -1; + memo[i][1] = -1; + } + + return Math.max(dfs(0, 1, nums), dfs(1, 0, nums)); + } + + private int dfs(int i, int flag, int[] nums) { + if (i >= nums.length || (flag == 1 && i == nums.length - 1)) + return 0; + if (memo[i][flag] != -1) + return memo[i][flag]; + memo[i][flag] = Math.max(dfs(i + 1, flag, nums), + nums[i] + dfs(i + 2, flag | (i == 0 ? 1 : 0), nums)); + return memo[i][flag]; + } +} +``` + +```cpp +class Solution { + vector> memo; + +public: + int rob(vector& nums) { + if (nums.size() == 1) return nums[0]; + + memo.resize(nums.size(), vector(2, -1)); + return max(dfs(0, 1, nums), dfs(1, 0, nums)); + } + +private: + int dfs(int i, int flag, vector& nums) { + if (i >= nums.size() || (flag == 1 && i == nums.size() - 1)) + return 0; + if (memo[i][flag] != -1) + return memo[i][flag]; + memo[i][flag] = max(dfs(i + 1, flag, nums), + nums[i] + dfs(i + 2, flag | (i == 0 ? 1 : 0), nums)); + return memo[i][flag]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + if (nums.length === 1) return nums[0]; + + const n = nums.length; + const memo = Array.from({ length: n }, () => Array(2).fill(-1)); + + const dfs = (i, flag) => { + if (i >= n || (flag && (i === n - 1))) + return 0; + if (memo[i][flag] !== -1) + return memo[i][flag]; + + memo[i][flag] = Math.max( + dfs(i + 1, flag), + nums[i] + dfs(i + 2, flag | (i === 0)) + ); + return memo[i][flag]; + } + + return Math.max(dfs(0, 1), dfs(1, 0)); + } +} +``` + +```csharp +public class Solution { + private int[][] memo; + + public int Rob(int[] nums) { + if (nums.Length == 1) return nums[0]; + + memo = new int[nums.Length][]; + for (int i = 0; i < nums.Length; i++) { + memo[i] = new int[] { -1, -1 }; + } + + return Math.Max(Dfs(0, 1, nums), Dfs(1, 0, nums)); + } + + private int Dfs(int i, int flag, int[] nums) { + if (i >= nums.Length || (flag == 1 && i == nums.Length - 1)) + return 0; + if (memo[i][flag] != -1) + return memo[i][flag]; + memo[i][flag] = Math.Max(Dfs(i + 1, flag, nums), + nums[i] + Dfs(i + 2, flag | (i == 0 ? 1 : 0), nums)); + return memo[i][flag]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. DP (Tabulation) + +::tabs-start + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + if len(nums) == 1: + return nums[0] + return max(self.helper(nums[1:]), + self.helper(nums[:-1])) + + def helper(self, nums: List[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + dp = [0] * len(nums) + dp[0] = nums[0] + dp[1] = max(nums[0], nums[1]) + + for i in range(2, len(nums)): + dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]) + + return dp[-1] +``` + +```java +public class Solution { + public int rob(int[] nums) { + if (nums.length == 1) return nums[0]; + + return Math.max(helper(Arrays.copyOfRange(nums, 1, nums.length)), + helper(Arrays.copyOfRange(nums, 0, nums.length - 1))); + } + + private int helper(int[] nums) { + if (nums.length == 0) return 0; + if (nums.length == 1) return nums[0]; + + int[] dp = new int[nums.length]; + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + + for (int i = 2; i < nums.length; i++) { + dp[i] = Math.max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp[nums.length - 1]; + } +} +``` + +```cpp +class Solution { +public: + int rob(std::vector& nums) { + if (nums.size() == 1) return nums[0]; + + return max(helper(vector(nums.begin() + 1, nums.end())), + helper(vector(nums.begin(), nums.end() - 1))); + } + + int helper(vector nums) { + if (nums.empty()) return 0; + if (nums.size() == 1) return nums[0]; + + vector dp(nums.size()); + dp[0] = nums[0]; + dp[1] = max(nums[0], nums[1]); + + for (int i = 2; i < nums.size(); i++) { + dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp.back(); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + if (nums.length === 0) return 0; + if (nums.length === 1) return nums[0]; + + return Math.max(this.helper(nums.slice(1)), + this.helper(nums.slice(0, -1))); + } + + /** + * @param {number[]} nums + * @return {number} + */ + helper(nums) { + if (nums.length === 0) return 0; + if (nums.length === 1) return nums[0]; + + const dp = new Array(nums.length); + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + + for (let i = 2; i < nums.length; i++) { + dp[i] = Math.max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp[nums.length - 1]; + } +} +``` + +```csharp +public class Solution { + public int Rob(int[] nums) { + if (nums.Length == 0) return 0; + if (nums.Length == 1) return nums[0]; + + return Math.Max(Helper(nums[1..]), Helper(nums[..^1])); + } + + private int Helper(int[] nums) { + if (nums.Length == 0) return 0; + if (nums.Length == 1) return nums[0]; + + int[] dp = new int[nums.Length]; + dp[0] = nums[0]; + dp[1] = Math.Max(nums[0], nums[1]); + + for (int i = 2; i < nums.Length; i++) { + dp[i] = Math.Max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp[^1]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. DP (Space Optimized) + +::tabs-start + +```python +class Solution: + + def rob(self, nums: List[int]) -> int: + return max(nums[0], self.helper(nums[1:]), + self.helper(nums[:-1])) + + def helper(self, nums): + rob1, rob2 = 0, 0 + + for num in nums: + newRob = max(rob1 + num, rob2) + rob1 = rob2 + rob2 = newRob + return rob2 +``` + +```java +public class Solution { + + public int rob(int[] nums) { + return Math.max(nums[0], + Math.max(helper(Arrays.copyOfRange(nums, 1, nums.length)), + helper(Arrays.copyOfRange(nums, 0, nums.length - 1)))); + } + + private int helper(int[] nums) { + int rob1 = 0, rob2 = 0; + + for (int num : nums) { + int newRob = Math.max(rob1 + num, rob2); + rob1 = rob2; + rob2 = newRob; + } + return rob2; + } +} +``` + +```cpp +class Solution { +public: + int rob(vector& nums) { + vector nums1(nums.begin() + 1, nums.end()); + vector nums2(nums.begin(), nums.end() - 1); + return max(nums[0], + max(helper(nums1), helper(nums2))); + } + +private: + int helper(vector& nums) { + int rob1 = 0, rob2 = 0; + for (int num : nums) { + int newRob = max(rob1 + num, rob2); + rob1 = rob2; + rob2 = newRob; + } + return rob2; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + return Math.max( + nums[0], + Math.max( + this.helper(nums.slice(1)), + this.helper(nums.slice(0, -1)), + ), + ); + } + + /** + * @param {number[]} nums + * @return {number} + */ + helper(nums) { + let rob1 = 0; + let rob2 = 0; + for (const num of nums) { + const newRob = Math.max(rob1 + num, rob2); + rob1 = rob2; + rob2 = newRob; + } + return rob2; + } +} +``` + +```csharp +public class Solution { + + public int Rob(int[] nums) { + if (nums.Length == 1) + return nums[0]; + + return Math.Max(Helper(nums[1..]), + Helper(nums[..^1])); + } + + private int Helper(int[] nums) { + int rob1 = 0, rob2 = 0; + foreach (int num in nums) { + int newRob = Math.Max(rob1 + num, rob2); + rob1 = rob2; + rob2 = newRob; + } + return rob2; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/house-robber.md b/articles/house-robber.md new file mode 100644 index 000000000..bdb292978 --- /dev/null +++ b/articles/house-robber.md @@ -0,0 +1,421 @@ +## 1. Recursion + +::tabs-start + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + + def dfs(i): + if i >= len(nums): + return 0 + return max(dfs(i + 1), + nums[i] + dfs(i + 2)) + + return dfs(0) +``` + +```java +public class Solution { + public int rob(int[] nums) { + return dfs(nums, 0); + } + + private int dfs(int[] nums, int i) { + if (i >= nums.length) { + return 0; + } + return Math.max(dfs(nums, i + 1), + nums[i] + dfs(nums, i + 2)); + } +} +``` + +```cpp +class Solution { +public: + int rob(vector& nums) { + return dfs(nums, 0); + } + + int dfs(vector& nums, int i) { + if (i >= nums.size()) { + return 0; + } + return max(dfs(nums, i + 1), + nums[i] + dfs(nums, i + 2)); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + + const dfs = (i) => { + if (i >= nums.length) { + return 0; + } + return Math.max(dfs(i + 1), + nums[i] + dfs(i + 2)); + } + return dfs(0); + } +} +``` + +```csharp +public class Solution { + public int Rob(int[] nums) { + return Dfs(nums, 0); + } + + private int Dfs(int[] nums, int i) { + if (i >= nums.Length) { + return 0; + } + return Math.Max(Dfs(nums, i + 1), + nums[i] + Dfs(nums, i + 2)); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(2 ^ n)$ +* Space complexity: $O(n)$ + +--- + +## 2. DP (Memoization) + +::tabs-start + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + memo = [-1] * len(nums) + + def dfs(i): + if i >= len(nums): + return 0 + if memo[i] != -1: + return memo[i] + memo[i] = max(dfs(i + 1), nums[i] + dfs(i + 2)) + return memo[i] + + return dfs(0) +``` + +```java +public class Solution { + private int[] memo; + + public int rob(int[] nums) { + memo = new int[nums.length]; + Arrays.fill(memo, -1); + return dfs(nums, 0); + } + + private int dfs(int[] nums, int i) { + if (i >= nums.length) { + return 0; + } + if (memo[i] != -1) { + return memo[i]; + } + memo[i] = Math.max(dfs(nums, i + 1), + nums[i] + dfs(nums, i + 2)); + return memo[i]; + } +} +``` + +```cpp +class Solution { +public: + vector memo; + + int rob(vector& nums) { + memo.resize(nums.size(), -1); + return dfs(nums, 0); + } + + int dfs(vector& nums, int i) { + if (i >= nums.size()) { + return 0; + } + if (memo[i] != -1) { + return memo[i]; + } + memo[i] = max(dfs(nums, i + 1), + nums[i] + dfs(nums, i + 2)); + return memo[i]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + const memo = new Int32Array(nums.length).fill(-1); + const dfs = (i) => { + if (i >= nums.length) { + return 0; + } + if (memo[i] !== -1) { + return memo[i]; + } + return memo[i] = Math.max(dfs(i + 1), + nums[i] + dfs(i + 2)); + } + return dfs(0); + } +} +``` + +```csharp +public class Solution { + private int[] memo; + + public int Rob(int[] nums) { + memo = new int[nums.Length]; + for (int i = 0; i < nums.Length; i++) { + memo[i] = -1; + } + return Dfs(nums, 0); + } + + private int Dfs(int[] nums, int i) { + if (i >= nums.Length) { + return 0; + } + if (memo[i] != -1) { + return memo[i]; + } + memo[i] = Math.Max(Dfs(nums, i + 1), + nums[i] + Dfs(nums, i + 2)); + return memo[i]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. DP (Tabulation) + +::tabs-start + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + if not nums: + return 0 + if len(nums) == 1: + return nums[0] + + dp = [0] * len(nums) + dp[0] = nums[0] + dp[1] = max(nums[0], nums[1]) + + for i in range(2, len(nums)): + dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]) + + return dp[-1] +``` + +```java +public class Solution { + public int rob(int[] nums) { + if (nums.length == 0) return 0; + if (nums.length == 1) return nums[0]; + + int[] dp = new int[nums.length]; + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + + for (int i = 2; i < nums.length; i++) { + dp[i] = Math.max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp[nums.length - 1]; + } +} +``` + +```cpp +class Solution { +public: + int rob(vector& nums) { + if (nums.empty()) return 0; + if (nums.size() == 1) return nums[0]; + + vector dp(nums.size()); + dp[0] = nums[0]; + dp[1] = max(nums[0], nums[1]); + + for (int i = 2; i < nums.size(); i++) { + dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp[nums.size() - 1]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + if (nums.length === 0) return 0; + if (nums.length === 1) return nums[0]; + + const dp = new Array(nums.length).fill(0); + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + + for (let i = 2; i < nums.length; i++) { + dp[i] = Math.max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp[nums.length - 1]; + } +} +``` + +```csharp +public class Solution { + public int Rob(int[] nums) { + if (nums.Length == 0) return 0; + if (nums.Length == 1) return nums[0]; + + int[] dp = new int[nums.Length]; + dp[0] = nums[0]; + dp[1] = Math.Max(nums[0], nums[1]); + + for (int i = 2; i < nums.Length; i++) { + dp[i] = Math.Max(dp[i - 1], nums[i] + dp[i - 2]); + } + + return dp[nums.Length - 1]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. DP (Space Optimized) + +::tabs-start + +```python +class Solution: + def rob(self, nums: List[int]) -> int: + rob1, rob2 = 0, 0 + + for num in nums: + temp = max(num + rob1, rob2) + rob1 = rob2 + rob2 = temp + return rob2 +``` + +```java +public class Solution { + public int rob(int[] nums) { + int rob1 = 0, rob2 = 0; + + for (int num : nums) { + int temp = Math.max(num + rob1, rob2); + rob1 = rob2; + rob2 = temp; + } + return rob2; + } +} +``` + +```cpp +class Solution { +public: + int rob(vector& nums) { + int rob1 = 0, rob2 = 0; + + for (int num : nums) { + int temp = max(num + rob1, rob2); + rob1 = rob2; + rob2 = temp; + } + return rob2; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} nums + * @return {number} + */ + rob(nums) { + let rob1 = 0; + let rob2 = 0; + + for (const num of nums) { + const temp = Math.max(num + rob1, rob2); + rob1 = rob2; + rob2 = temp; + } + return rob2; + } +} +``` + +```csharp +public class Solution { + public int Rob(int[] nums) { + int rob1 = 0, rob2 = 0; + + foreach (int num in nums) { + int temp = Math.Max(num + rob1, rob2); + rob1 = rob2; + rob2 = temp; + } + return rob2; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file diff --git a/articles/longest-palindromic-substring.md b/articles/longest-palindromic-substring.md new file mode 100644 index 000000000..73e9af55a --- /dev/null +++ b/articles/longest-palindromic-substring.md @@ -0,0 +1,670 @@ +## 1. Brute Force + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> str: + res, resLen = "", 0 + + for i in range(len(s)): + for j in range(i, len(s)): + l, r = i, j + while l < r and s[l] == s[r]: + l += 1 + r -= 1 + + if l >= r and resLen < (j - i + 1): + res = s[i : j + 1] + resLen = j - i + 1 + return res +``` + +```java +public class Solution { + public String longestPalindrome(String s) { + String res = ""; + int resLen = 0; + + for (int i = 0; i < s.length(); i++) { + for (int j = i; j < s.length(); j++) { + int l = i, r = j; + while (l < r && s.charAt(l) == s.charAt(r)) { + l++; + r--; + } + + if (l >= r && resLen < (j - i + 1)) { + res = s.substring(i, j + 1); + resLen = j - i + 1; + } + } + } + + return res; + } +} +``` + +```cpp +class Solution { +public: + string longestPalindrome(string s) { + string res = ""; + int resLen = 0; + + for (int i = 0; i < s.size(); i++) { + for (int j = i; j < s.size(); j++) { + int l = i, r = j; + while (l < r && s[l] == s[r]) { + l++; + r--; + } + + if (l >= r && resLen < (j - i + 1)) { + res = s.substr(i, j - i + 1); + resLen = j - i + 1; + } + } + } + + return res; + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string} + */ + longestPalindrome(s) { + let res = ""; + let resLen = 0; + + for (let i = 0; i < s.length; i++) { + for (let j = i; j < s.length; j++) { + let l = i, r = j; + while (l < r && s[l] === s[r]) { + l++; + r--; + } + + if (l >= r && resLen < (j - i + 1)) { + res = s.slice(i, j + 1); + resLen = j - i + 1; + } + } + } + + return res; + } +} +``` + +```csharp +public class Solution { + public string LongestPalindrome(string s) { + string res = ""; + int resLen = 0; + + for (int i = 0; i < s.Length; i++) { + for (int j = i; j < s.Length; j++) { + int l = i, r = j; + while (l < r && s[l] == s[r]) { + l++; + r--; + } + + if (l >= r && resLen < (j - i + 1)) { + res = s.Substring(i, j - i + 1); + resLen = j - i + 1; + } + } + } + + return res; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 3)$ +* Space complexity: $O(1)$ + +--- + +## 2. Dynamic Programming + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> str: + resIdx, resLen = 0, 0 + n = len(s) + + dp = [[False] * n for _ in range(n)] + + for i in range(n - 1, -1, -1): + for j in range(i, n): + if s[i] == s[j] and (j - i <= 2 or dp[i + 1][j - 1]): + dp[i][j] = True + if resLen < (j - i + 1): + resIdx = i + resLen = j - i + 1 + + return s[resIdx : resIdx + resLen] +``` + +```java +public class Solution { + public String longestPalindrome(String s) { + int resIdx = 0, resLen = 0; + int n = s.length(); + + boolean[][] dp = new boolean[n][n]; + + for (int i = n - 1; i >= 0; i--) { + for (int j = i; j < n; j++) { + if (s.charAt(i) == s.charAt(j) && + (j - i <= 2 || dp[i + 1][j - 1])) { + + dp[i][j] = true; + if (resLen < (j - i + 1)) { + resIdx = i; + resLen = j - i + 1; + } + } + } + } + + return s.substring(resIdx, resIdx + resLen); + } +} +``` + +```cpp +class Solution { +public: + string longestPalindrome(string s) { + int resIdx = 0, resLen = 0; + int n = s.size(); + + vector> dp(n, vector(n, false)); + + for (int i = n - 1; i >= 0; i--) { + for (int j = i; j < n; j++) { + if (s[i] == s[j] && + (j - i <= 2 || dp[i + 1][j - 1])) { + + dp[i][j] = true; + if (resLen < (j - i + 1)) { + resIdx = i; + resLen = j - i + 1; + } + } + } + } + + return s.substr(resIdx, resLen); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string} + */ + longestPalindrome(s) { + let resIdx = 0, resLen = 0; + const n = s.length; + + const dp = Array.from({ length: n }, () => Array(n).fill(false)); + + for (let i = n - 1; i >= 0; i--) { + for (let j = i; j < n; j++) { + if (s[i] === s[j] && + (j - i <= 2 || dp[i + 1][j - 1])) { + + dp[i][j] = true; + if (resLen < (j - i + 1)) { + resIdx = i; + resLen = j - i + 1; + } + } + } + } + + return s.slice(resIdx, resIdx + resLen); + } +} +``` + +```csharp +public class Solution { + public string LongestPalindrome(string s) { + int resIdx = 0, resLen = 0; + int n = s.Length; + + bool[,] dp = new bool[n, n]; + + for (int i = n - 1; i >= 0; i--) { + for (int j = i; j < n; j++) { + if (s[i] == s[j] && + (j - i <= 2 || dp[i + 1, j - 1])) { + + dp[i, j] = true; + if (resLen < (j - i + 1)) { + resIdx = i; + resLen = j - i + 1; + } + } + } + } + + return s.Substring(resIdx, resLen); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(n ^ 2)$ + +--- + +## 3. Two Pointers + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> str: + resIdx = 0 + resLen = 0 + + for i in range(len(s)): + # odd length + l, r = i, i + while l >= 0 and r < len(s) and s[l] == s[r]: + if (r - l + 1) > resLen: + resIdx = l + resLen = r - l + 1 + l -= 1 + r += 1 + + # even length + l, r = i, i + 1 + while l >= 0 and r < len(s) and s[l] == s[r]: + if (r - l + 1) > resLen: + resIdx = l + resLen = r - l + 1 + l -= 1 + r += 1 + + return s[resIdx : resIdx + resLen] +``` + +```java +class Solution { + public String longestPalindrome(String s) { + int resLen = 0, resIdx = 0; + + for (int i = 0; i < s.length(); i++) { + // odd length + int l = i, r = i; + while (l >= 0 && r < s.length() && + s.charAt(l) == s.charAt(r)) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + + // even length + l = i; + r = i + 1; + while (l >= 0 && r < s.length() && + s.charAt(l) == s.charAt(r)) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + } + + return s.substring(resIdx, resIdx + resLen); + } +} +``` + +```cpp +class Solution { +public: + string longestPalindrome(string s) { + int resLen = 0, resIdx = 0; + + for (int i = 0; i < s.size(); i++) { + // odd length + int l = i, r = i; + while (l >= 0 && r < s.size() && + s[l] == s[r]) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + + // even length + l = i; + r = i + 1; + while (l >= 0 && r < s.size() && + s[l] == s[r]) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + } + + return s.substr(resIdx, resLen); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {string} + */ + longestPalindrome(s) { + let resIdx = 0; + let resLen = 0; + + for (let i = 0; i < s.length; i++) { + // odd length + let l = i; + let r = i; + while (l >= 0 && r < s.length && + s.charAt(l) === s.charAt(r)) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + + // even length + l = i; + r = i + 1; + while (l >= 0 && r < s.length && + s.charAt(l) === s.charAt(r)) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + } + + return s.substring(resIdx, resIdx + resLen); + } +} +``` + +```csharp +public class Solution { + public string LongestPalindrome(string s) { + int resLen = 0, resIdx = 0; + + for (int i = 0; i < s.Length; i++) { + // odd length + int l = i, r = i; + while (l >= 0 && r < s.Length && + s[l] == s[r]) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + + // even length + l = i; + r = i + 1; + while (l >= 0 && r < s.Length && + s[l] == s[r]) { + if (r - l + 1 > resLen) { + resIdx = l; + resLen = r - l + 1; + } + l--; + r++; + } + } + + return s.Substring(resIdx, resLen); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n ^ 2)$ +* Space complexity: $O(1)$ + +--- + +## 4. Manacher's Algorithm + +::tabs-start + +```python +class Solution: + def longestPalindrome(self, s: str) -> str: + def manacher(s): + t = '#' + '#'.join(s) + '#' + n = len(t) + p = [0] * n + l, r = 0, 0 + for i in range(n): + p[i] = min(r - i, p[l + (r - i)]) if i < r else 0 + while (i + p[i] + 1 < n and i - p[i] - 1 >= 0 + and t[i + p[i] + 1] == t[i - p[i] - 1]): + p[i] += 1 + if i + p[i] > r: + l, r = i - p[i], i + p[i] + return p + + p = manacher(s) + resLen, center_idx = max((v, i) for i, v in enumerate(p)) + resIdx = (center_idx - resLen) // 2 + return s[resIdx : resIdx + resLen] +``` + +```java +public class Solution { + public int[] manacher(String s) { + StringBuilder t = new StringBuilder("#"); + for (char c : s.toCharArray()) { + t.append(c).append("#"); + } + int n = t.length(); + int[] p = new int[n]; + int l = 0, r = 0; + for (int i = 0; i < n; i++) { + p[i] = (i < r) ? Math.min(r - i, p[l + (r - i)]) : 0; + while (i + p[i] + 1 < n && i - p[i] - 1 >= 0 && + t.charAt(i + p[i] + 1) == t.charAt(i - p[i] - 1)) { + p[i]++; + } + if (i + p[i] > r) { + l = i - p[i]; + r = i + p[i]; + } + } + return p; + } + + public String longestPalindrome(String s) { + int[] p = manacher(s); + int resLen = 0, center_idx = 0; + for (int i = 0; i < p.length; i++) { + if (p[i] > resLen) { + resLen = p[i]; + center_idx = i; + } + } + int resIdx = (center_idx - resLen) / 2; + return s.substring(resIdx, resIdx + resLen); + } +} +``` + +```cpp +class Solution { +public: + vector manacher(string& s) { + string t = "#" + string(1, s[0]); + for (int i = 1; i < s.size(); ++i) + t += "#" + string(1, s[i]); + t += "#"; + int n = t.size(); + vector p(n, 0); + int l = 0, r = 0; + for (int i = 0; i < n; i++) { + p[i] = (i < r) ? min(r - i, p[l + (r - i)]) : 0; + while (i + p[i] + 1 < n && i - p[i] - 1 >= 0 && + t[i + p[i] + 1] == t[i - p[i] - 1]) + p[i]++; + if (i + p[i] > r) + l = i - p[i], r = i + p[i]; + } + return p; + } + + string longestPalindrome(string s) { + vector p = manacher(s); + int resLen = 0, center_idx = 0; + for (int i = 0; i < p.size(); i++) { + if (p[i] > resLen) { + resLen = p[i]; + center_idx = i; + } + } + int resIdx = (center_idx - resLen) / 2; + return s.substr(resIdx, resLen); + } +}; +``` + +```javascript +class Solution { + /** + * @param {string} s + * @return {number[]} + */ + manacher(s) { + const t = '#' + s.split('').join('#') + '#'; + const n = t.length; + const p = new Array(n).fill(0); + let l = 0, r = 0; + for (let i = 0; i < n; i++) { + p[i] = (i < r) ? Math.min(r - i, p[l + (r - i)]) : 0; + while (i + p[i] + 1 < n && i - p[i] - 1 >= 0 && + t[i + p[i] + 1] === t[i - p[i] - 1]) { + p[i]++; + } + if (i + p[i] > r) { + l = i - p[i]; + r = i + p[i]; + } + } + return p; + } + + /** + * @param {string} s + * @return {string} + */ + longestPalindrome(s) { + const p = this.manacher(s); + let resLen = 0, center_idx = 0; + for (let i = 0; i < p.length; i++) { + if (p[i] > resLen) { + resLen = p[i]; + center_idx = i; + } + } + const resIdx = (center_idx - resLen) / 2; + return s.substring(resIdx, resIdx + resLen); + } +} +``` + +```csharp +public class Solution { + public int[] Manacher(string s) { + string t = "#" + string.Join("#", s.ToCharArray()) + "#"; + int n = t.Length; + int[] p = new int[n]; + int l = 0, r = 0; + for (int i = 0; i < n; i++) { + p[i] = (i < r) ? Math.Min(r - i, p[l + (r - i)]) : 0; + while (i + p[i] + 1 < n && i - p[i] - 1 >= 0 && + t[i + p[i] + 1] == t[i - p[i] - 1]) { + p[i]++; + } + if (i + p[i] > r) { + l = i - p[i]; + r = i + p[i]; + } + } + return p; + } + + public string LongestPalindrome(string s) { + int[] p = Manacher(s); + int resLen = 0, center_idx = 0; + for (int i = 0; i < p.Length; i++) { + if (p[i] > resLen) { + resLen = p[i]; + center_idx = i; + } + } + int resIdx = (center_idx - resLen) / 2; + return s.Substring(resIdx, resLen); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ \ No newline at end of file diff --git a/articles/min-cost-climbing-stairs.md b/articles/min-cost-climbing-stairs.md new file mode 100644 index 000000000..3e165f5be --- /dev/null +++ b/articles/min-cost-climbing-stairs.md @@ -0,0 +1,381 @@ +## 1. Recursion + +::tabs-start + +```python +class Solution: + def minCostClimbingStairs(self, cost: List[int]) -> int: + + def dfs(i): + if i >= len(cost): + return 0 + return cost[i] + min(dfs(i + 1), dfs(i + 2)) + + return min(dfs(0), dfs(1)) +``` + +```java +public class Solution { + public int minCostClimbingStairs(int[] cost) { + + return Math.min(dfs(cost, 0), dfs(cost, 1)); + } + + private int dfs(int[] cost, int i) { + if (i >= cost.length) { + return 0; + } + return cost[i] + Math.min(dfs(cost, i + 1), + dfs(cost, i + 2)); + } +} +``` + +```cpp +class Solution { +public: + int minCostClimbingStairs(vector& cost) { + return min(dfs(cost, 0), dfs(cost, 1)); + } + + int dfs(vector& cost, int i) { + if (i >= cost.size()) { + return 0; + } + return cost[i] + min(dfs(cost, i + 1), + dfs(cost, i + 2)); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} cost + * @return {number} + */ + minCostClimbingStairs(cost) { + const dfs = (i) => { + if (i >= cost.length) { + return 0; + } + return cost[i] + Math.min(dfs(i + 1), dfs(i + 2)); + } + return Math.min(dfs(0), dfs(1)); + } +} +``` + +```csharp +public class Solution { + public int MinCostClimbingStairs(int[] cost) { + return Math.Min(Dfs(cost, 0), Dfs(cost, 1)); + } + + private int Dfs(int[] cost, int i) { + if (i >= cost.Length) { + return 0; + } + return cost[i] + Math.Min(Dfs(cost, i + 1), + Dfs(cost, i + 2)); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(2 ^ n)$ +* Space complexity: $O(n)$ + +--- + +## 2. DP (Memoization) + +::tabs-start + +```python +class Solution: + def minCostClimbingStairs(self, cost: List[int]) -> int: + memo = [-1] * len(cost) + + def dfs(i): + if i >= len(cost): + return 0 + if memo[i] != -1: + return memo[i] + memo[i] = cost[i] + min(dfs(i + 1), dfs(i + 2)) + return memo[i] + + return min(dfs(0), dfs(1)) +``` + +```java +public class Solution { + int[] memo; + + public int minCostClimbingStairs(int[] cost) { + memo = new int[cost.length]; + Arrays.fill(memo, -1); + return Math.min(dfs(cost, 0), dfs(cost, 1)); + } + + private int dfs(int[] cost, int i) { + if (i >= cost.length) { + return 0; + } + if (memo[i] != -1) { + return memo[i]; + } + memo[i] = cost[i] + Math.min(dfs(cost, i + 1), + dfs(cost, i + 2)); + return memo[i]; + } +} +``` + +```cpp +class Solution { +public: + vector memo; + + int minCostClimbingStairs(vector& cost) { + memo.resize(cost.size(), -1); + return min(dfs(cost, 0), dfs(cost, 1)); + } + + int dfs(vector& cost, int i) { + if (i >= cost.size()) { + return 0; + } + if (memo[i] != -1) { + return memo[i]; + } + memo[i] = cost[i] + min(dfs(cost, i + 1), + dfs(cost, i + 2)); + return memo[i]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} cost + * @return {number} + */ + minCostClimbingStairs(cost) { + const memo = new Int32Array(cost.length).fill(-1); + const dfs = (i) => { + if (i >= cost.length) { + return 0; + } + if (memo[i] !== -1) { + return memo[i]; + } + memo[i] = cost[i] + Math.min(dfs(i + 1), + dfs(i + 2)); + return memo[i]; + } + return Math.min(dfs(0), dfs(1)); + } +} +``` + +```csharp +public class Solution { + int[] memo; + + public int MinCostClimbingStairs(int[] cost) { + memo = new int[cost.Length]; + Array.Fill(memo, -1); + return Math.Min(Dfs(cost, 0), Dfs(cost, 1)); + } + + private int Dfs(int[] cost, int i) { + if (i >= cost.Length) { + return 0; + } + if (memo[i] != -1) { + return memo[i]; + } + memo[i] = cost[i] + Math.Min(Dfs(cost, i + 1), + Dfs(cost, i + 2)); + return memo[i]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 3. DP (Tabulation) + +::tabs-start + +```python +class Solution: + def minCostClimbingStairs(self, cost: List[int]) -> int: + n = len(cost) + dp = [0] * (n + 1) + + for i in range(2, n + 1): + dp[i] = min(dp[i - 1] + cost[i - 1], + dp[i - 2] + cost[i - 2]) + + return dp[n] +``` + +```java +public class Solution { + public int minCostClimbingStairs(int[] cost) { + int n = cost.length; + int[] dp = new int[n + 1]; + + for (int i = 2; i <= n; i++) { + dp[i] = Math.min(dp[i - 1] + cost[i - 1], + dp[i - 2] + cost[i - 2]); + } + + return dp[n]; + } +} +``` + +```cpp +class Solution { +public: + int minCostClimbingStairs(vector& cost) { + int n = cost.size(); + vector dp(n + 1); + + for (int i = 2; i <= n; i++) { + dp[i] = min(dp[i - 1] + cost[i - 1], + dp[i - 2] + cost[i - 2]); + } + + return dp[n]; + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} cost + * @return {number} + */ + minCostClimbingStairs(cost) { + const n = cost.length; + const dp = new Array(n + 1).fill(0); + + for (let i = 2; i <= n; i++) { + dp[i] = Math.min(dp[i - 1] + cost[i - 1], + dp[i - 2] + cost[i - 2]); + } + + return dp[n]; + } +} +``` + +```csharp +public class Solution { + public int MinCostClimbingStairs(int[] cost) { + int n = cost.Length; + int[] dp = new int[n + 1]; + + for (int i = 2; i <= n; i++) { + dp[i] = Math.Min(dp[i - 1] + cost[i - 1], + dp[i - 2] + cost[i - 2]); + } + + return dp[n]; + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(n)$ + +--- + +## 4. DP (Space Optimized) + +::tabs-start + +```python +class Solution: + def minCostClimbingStairs(self, cost: List[int]) -> int: + for i in range(len(cost) - 3, -1, -1): + cost[i] += min(cost[i + 1], cost[i + 2]) + + return min(cost[0], cost[1]) +``` + +```java +public class Solution { + public int minCostClimbingStairs(int[] cost) { + for (int i = cost.length - 3; i >= 0; i--) { + cost[i] += Math.min(cost[i + 1], cost[i + 2]); + } + return Math.min(cost[0], cost[1]); + } +} +``` + +```cpp +class Solution { +public: + int minCostClimbingStairs(vector& cost) { + for (int i = cost.size() - 3; i >= 0; i--) { + cost[i] += min(cost[i + 1], cost[i + 2]); + } + return min(cost[0], cost[1]); + } +}; +``` + +```javascript +class Solution { + /** + * @param {number[]} cost + * @return {number} + */ + minCostClimbingStairs(cost) { + for (let i = cost.length - 3; i >= 0; i--) { + cost[i] += Math.min(cost[i + 1], cost[i + 2]); + } + return Math.min(cost[0], cost[1]); + } +} +``` + +```csharp +public class Solution { + public int MinCostClimbingStairs(int[] cost) { + for (int i = cost.Length - 3; i >= 0; i--) { + cost[i] += Math.Min(cost[i + 1], cost[i + 2]); + } + return Math.Min(cost[0], cost[1]); + } +} +``` + +::tabs-end + +### Time & Space Complexity + +* Time complexity: $O(n)$ +* Space complexity: $O(1)$ \ No newline at end of file