From 1dfd409aae57c4b6efffe392e1c4719485b43ffc Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Wed, 5 Jun 2024 08:39:06 +0530 Subject: [PATCH 1/3] Climibing Stairs solution added --- .../0010-paths-to-reach-origin.md | 608 ++++++++++++++++++ .../gfg-solutions/0020-climbing-stairs.md | 531 +++++++++++++++ 2 files changed, 1139 insertions(+) create mode 100644 dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md create mode 100644 dsa-solutions/gfg-solutions/0020-climbing-stairs.md diff --git a/dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md b/dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md new file mode 100644 index 000000000..e5b69239d --- /dev/null +++ b/dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md @@ -0,0 +1,608 @@ +--- + +id: paths-to-reach-origin +title: Paths to Reach Origin +sidebar_label: 0010 Paths to Reach Origin +tags: +- Dynamic Programming +- Backtracking +- Recursion +- Combinatorics +- JavaScript +- Python +- Java +- C++ +description: "This document explores finding the number of paths to reach the origin (0, 0) on a grid." + +--- + +## Problem Description + +Imagine you are standing on a grid at point (`x`, `y`). You can only move down (y decreases) or right (x increases). Your goal is to reach the origin (0, 0). This document discusses how to find the total number of unique paths you can take to reach the origin. + +### Example + +**Input:** x = 3, y = 2 (Starting at point (3, 2)) + +**Output:** 3 + +There are three unique paths to reach the origin: + +1. Down, Down, Right (D-D-R) +2. Down, Right, Down (D-R-D) +3. Right, Down, Down (R-D-D) + +--- + +## Solutions for Finding Paths + +There are multiple approaches to solve this problem. Here, we will explore four common techniques: + + + + +### Approach 1: Recursive + +A recursive approach solves the problem by breaking down the larger problem into smaller subproblems. + +#### Implementation + +```javascript +class Solution { + ways(x, y) { + return this.help(x, y); + } + + help(i, j) { + // Base case + if (i === 0 && j === 0) return 1; + if (i < 0 || j < 0) return 0; + + // Recursive calls + const down = this.help(i - 1, j); + const right = this.help(i, j - 1); + + return down + right; + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + ways(x, y) { + return this.help(x, y); + } + + help(i, j) { + // Base case + if (i === 0 && j === 0) return 1; + if (i < 0 || j < 0) return 0; + + // Recursive calls + const down = this.help(i - 1, j); + const right = this.help(i, j - 1); + + return down + right; + } + } + ``` + + + + + + ```python + class Solution: + def ways(self, x, y): + return self.help(x, y) + + def help(self, i, j): + # Base case + if i == 0 and j == 0: + return 1 + if i < 0 or j < 0: + return 0 + + # Recursive calls + down = self.help(i - 1, j) + right = self.help(i, j - 1) + + return down + right + ``` + + + + ```java + class Solution { + public int ways(int x, int y) { + return help(x, y); + } + + private int help(int i, int j) { + // Base case + if (i == 0 && j == 0) return 1; + if (i < 0 || j < 0) return 0; + + // Recursive calls + int down = help(i - 1, j); + int right = help(i, j - 1); + + return down + right; + } + } + ``` + + + + + ```cpp + class Solution { + public: + int ways(int x, int y) { + return help(x, y); + } + + int help(int i, int j) { + // Base case + if (i == 0 && j == 0) return 1; + if (i < 0 || j < 0) return 0; + + // Recursive calls + int down = help(i - 1, j); + int right = help(i, j - 1); + + return down + right; + } + }; + ``` + + + +#### Complexity Analysis + +**Time Complexity:** $O(2^{x+y})$ +- In the worst case, each move (left or down) results in two recursive calls, leading to an exponential number of calls. + +**Space Complexity:** $O(x + y)$ +- The space complexity is due to the maximum depth of the recursion stack. + + + + +### Approach 2: Memoization + +Memoization is an optimization technique where we store the results of expensive function calls and reuse them when the same inputs occur again. + +#### Implementation + +```javascript +class Solution { + constructor() { + this.memo = {}; + } + + ways(x, y) { + return this.help(x, y); + } + + help(i, j) { + // Base case + if (i === 0 && j === 0) return 1; + if (i < 0 || j < 0) return 0; + + const key = `${i},${j}`; + if (this.memo[key] !== undefined) return this.memo[key]; + + // Recursive calls + const down = this.help(i - 1, j); + const right = this.help(i, j - 1); + + this.memo[key] = down + right; + return this.memo[key]; + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + constructor() { + this.memo = {}; + } + + ways(x, y) { + return this.help(x, y); + } + + help(i, j) { + // Base case + if (i === 0 && j === 0) return 1; + if (i < 0 || j < 0) return 0; + + const key = `${i},${j}`; + if (this.memo[key] !== undefined) return this.memo[key]; + + // Recursive calls + const down = this.help(i - 1, j); + const right = this.help(i, j - 1); + + this.memo[key] = down + right; + return this.memo[key]; + } + } + ``` + + + + + + ```python + class Solution: + def __init__(self): + self.memo = {} + + def ways(self, x, y): + return self.help(x, y) + + def help(self, i, j): + # Base case + if i == 0 and j == 0: + return 1 + if i < 0 or j < 0: + return 0 + + key = (i, j) + if key in self.memo: + return self.memo[key] + + # Recursive calls + down = self.help(i - 1, j) + right = self.help(i, j - 1) + + self.memo[key] = down + right + return self.memo[key] + ``` + + + + + ```java + import java.util.HashMap; + import java.util.Map; + + class Solution { + private Map memo = new HashMap<>(); + + public int ways(int x, int y) { + return help(x, y); + } + + private int help(int i, int j) { + // Base case + if (i == 0 && j == 0) return 1; + if (i < 0 || j < 0) return 0; + + String key = i + "," + j; + if (memo.containsKey(key)) return memo.get(key); + + // Recursive calls + int down = help(i - 1, j); + int right = help(i, j - 1); + + memo.put(key, down + right); + return memo.get(key); + } + } + ``` + + + + ```cpp + #include + #include + using namespace std; + + class Solution { + unordered_map memo; + + public: + int ways(int x, int y) { + return help(x, y); + } + + int help(int i, int j) { + // Base case + if (i == 0 && j == 0) return 1; + if (i < 0 || j < 0) return 0; + + string key = to_string(i) + "," + to_string(j); + if (memo.find(key) != memo.end()) return memo[key]; + + // Recursive calls + int down = help(i - 1, j); + int right = help(i, j - 1); + + memo[key] = down + right; + return + + memo[key]; + } + }; + ``` + + + +#### Complexity Analisys + +**Time Complexity:** $O(x \cdot y)$ +- Each subproblem is solved once and stored in the memoization table. + +**Space Complexity:** $O(x \cdot y)$ +- Space is used for the memoization table. + + + + +### Approach 3: Tabulation + +Tabulation is a bottom-up dynamic programming technique where we solve smaller subproblems first and use their results to build up solutions to larger subproblems. + +#### Implementation + +```javascript +class Solution { + ways(x, y) { + const dp = Array.from({ length: x + 1 }, () => Array(y + 1).fill(0)); + dp[0][0] = 1; + + for (let i = 0; i <= x; i++) { + for (let j = 0; j <= y; j++) { + if (i > 0) dp[i][j] += dp[i - 1][j]; + if (j > 0) dp[i][j] += dp[i][j - 1]; + } + } + + return dp[x][y]; + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + ways(x, y) { + const dp = Array.from({ length: x + 1 }, () => Array(y + 1).fill(0)); + dp[0][0] = 1; + + for (let i = 0; i <= x; i++) { + for (let j = 0; j <= y; j++) { + if (i > 0) dp[i][j] += dp[i - 1][j]; + if (j > 0) dp[i][j] += dp[i][j - 1]; + } + } + + return dp[x][y]; + } + } + ``` + + + + + ```python + class Solution: + def ways(self, x, y): + dp = [[0] * (y + 1) for _ in range(x + 1)] + dp[0][0] = 1 + + for i in range(x + 1): + for j in range(y + 1): + if i > 0: + dp[i][j] += dp[i - 1][j] + if j > 0: + dp[i][j] += dp[i][j - 1] + + return dp[x][y] + ``` + + + + ```java + class Solution { + public int ways(int x, int y) { + int[][] dp = new int[x + 1][y + 1]; + dp[0][0] = 1; + + for (int i = 0; i <= x; i++) { + for (int j = 0; j <= y; j++) { + if (i > 0) dp[i][j] += dp[i - 1][j]; + if (j > 0) dp[i][j] += dp[i][j - 1]; + } + } + + return dp[x][y]; + } + } + ``` + + + + ```cpp + #include + using namespace std; + + class Solution { + public: + int ways(int x, int y) { + vector> dp(x + 1, vector(y + 1, 0)); + dp[0][0] = 1; + + for (int i = 0; i <= x; i++) { + for (int j = 0; j <= y; j++) { + if (i > 0) dp[i][j] += dp[i - 1][j]; + if (j > 0) dp[i][j] += dp[i][j - 1]; + } + } + + return dp[x][y]; + } + }; + ``` + + + +#### Complexity Analysis + +**Time Complexity:** $O(x \cdot y)$ +- Filling up the table involves computing values for $x \times y$ cells. + +**Space Complexity:** $O(x \cdot y)$ +- Space is used for the 2D table. + + + + +### Approach 4: Space Optimization + +Space optimization improves the efficiency of the tabulation method by reducing the amount of space used. + +#### Implementation + +```javascript +class Solution { + ways(x, y) { + const dp = Array(y + 1).fill(0); + dp[0] = 1; + + for (let i = 0; i <= x; i++) { + for (let j = 1; j <= y; j++) { + dp[j] += dp[j - 1]; + } + } + + return dp[y]; + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + ways(x, y) { + const dp = Array(y + 1).fill(0); + dp[0] = 1; + + for (let i = 0; i <= x; i++) { + for (let j = 1; j <= y; j++) { + dp[j] += dp[j - 1]; + } + } + + return dp[y]; + } + } + ``` + + + + + ```python + class Solution: + def ways(self, x, y): + dp = [0] * (y + 1) + dp[0] = 1 + + for i in range(x + 1): + for j in range(1, y + 1): + dp[j] += dp[j - 1] + + return dp[y] + ``` + + + + ```java + class Solution { + public int ways(int x, int y) { + int[] dp = new int[y + 1]; + dp[0] = 1; + + for (int i = 0; i <= x; i++) { + for (int j = 1; j <= y; j++) { + dp[j] += dp[j - 1]; + } + } + + return dp[y]; + } + } + ``` + + + + ```cpp + #include + using namespace std; + + class Solution { + public: + int ways(int x, int y) { + vector dp(y + 1, 0); + dp[0] = 1; + + for (int i = 0; i <= x; i++) { + for (int j = 1; j <= y; j++) { + dp[j] += dp[j - 1]; + } + } + + return dp[y]; + } + }; + ``` + + + +#### Complexity Analysis + +**Time Complexity:** $O(x \cdot y)$ +- The same number of computations as in tabulation. + +**Space Complexity:** $O(y)$ +- Only a single array of size $y + 1$ is used. + + + + +:::tip + +When choosing an approach, consider both time and space complexities. For smaller inputs, simpler approaches like recursion might be sufficient, but for larger inputs, optimized solutions like memoization, tabulation, or space-optimized tabulation are more efficient and practical. Always analyze the constraints and requirements of your problem to select the most appropriate method. + +Would you like any additional information or another example? + +::: + +--- + +## References + +- **LeetCode Problem**: [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) +- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/maximum-depth-of-binary-tree/solution/) +- **Authors GeeksforGeeks Profile:** [Vipul](https://www.geeksforgeeks.org/user/lakumvipwjge/) \ No newline at end of file diff --git a/dsa-solutions/gfg-solutions/0020-climbing-stairs.md b/dsa-solutions/gfg-solutions/0020-climbing-stairs.md new file mode 100644 index 000000000..7031582ef --- /dev/null +++ b/dsa-solutions/gfg-solutions/0020-climbing-stairs.md @@ -0,0 +1,531 @@ +--- +id: climbing-stairs +title: Climbing Stairs +sidebar_label: 0020 Climbing Stairs +tags: +- Dynamic Programming +- Recursion +- Memoization +- Tabulation +- Space Optimization +- JavaScript +- TypeScript +- Python +- Java +- C++ +description: "This document explores different approaches to solving the climbing stairs problem, including recursion, memoization, tabulation, and space optimization." +--- +## Problem + +You are climbing a staircase. It takes `n` steps to reach the top. + +Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? + +### Examples + +**Example 1:** + +Input: `n = 2` +Output: `2` +Explanation: There are two ways to climb to the top: +1. 1 step + 1 step +2. 2 steps + +**Example 2:** + +Input: `n = 3` +Output: `3` +Explanation: There are three ways to climb to the top: +1. 1 step + 1 step + 1 step +2. 1 step + 2 steps +3. 2 steps + 1 step + +### Constraints + +- $ 1 \leq n \leq 45 $ + +## Solution + +### Intuition + +To calculate the number of ways to climb the stairs, we can observe that when we are on the nth stair, we have two options: + +- Either we climbed one stair from the (n-1)th stair +- Or we climbed two stairs from the (n-2)th stair + +By leveraging this observation, we can break down the problem into smaller subproblems and apply the concept of the Fibonacci series. The base cases are when we are on the 1st stair (only one way to reach it) and the 2nd stair (two ways to reach it). By summing up the number of ways to reach the (n-1)th and (n-2)th stairs, we can compute the total number of ways to climb the stairs. This allows us to solve the problem efficiently using various dynamic programming techniques such as recursion, memoization, tabulation, or space optimization. + + + + +### Approach 1: Recursive + +A recursive approach solves the problem by breaking down the larger problem into smaller subproblems. + +#### Implementation + +```javascript +class Solution { + climbStairs(n) { + if (n === 0 || n === 1) { + return 1; + } + return this.climbStairs(n - 1) + this.climbStairs(n - 2); + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + climbStairs(n) { + if (n === 0 || n === 1) { + return 1; + } + return this.climbStairs(n - 1) + this.climbStairs(n - 2); + } + } + ``` + + + + + + ```python + class Solution: + def climbStairs(self, n: int) -> int: + if n == 0 or n == 1: + return 1 + return self.climbStairs(n-1) + self.climbStairs(n-2) + ``` + + + + ```java + class Solution { + public int climbStairs(int n) { + if (n == 0 || n == 1) { + return 1; + } + return climbStairs(n-1) + climbStairs(n-2); + } + } + ``` + + + + + ```cpp + class Solution { + public: + int ways(int x, int y) { + return help(x, y); + } + + int help(int i, int j) { + // Base case + if (i == 0 && j == 0) return 1; + if (i < 0 || j < 0) return 0; + + // Recursive calls + int down = help(i - 1, j); + int right = help(i, j - 1); + + return down + right; + } + }; + ``` + + + +#### Complexity Analysis + +**Time Complexity:** $O(2^{x+y})$ +- In the worst case, each move (left or down) results in two recursive calls, leading to an exponential number of calls. + +**Space Complexity:** $O(x + y)$ +- The space complexity is due to the maximum depth of the recursion stack. + + + + +### Approach 2: Memoization + +The memoization approach optimizes the recursive solution by caching previously computed results to avoid redundant calculations. + +#### Implementation + +```javascript +class Solution { + climbStairs(n, memo = new Map()) { + if (n === 0 || n === 1) { + return 1; + } + + if (!memo.has(n)) { + memo.set(n, this.climbStairs(n - 1, memo) + this.climbStairs(n - 2, memo)); + } + + return memo.get(n); + } + + climbStairs(n) { + const memo = new Map(); + return this.climbStairs(n, memo); + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + climbStairs(n, memo = new Map()) { + if (n === 0 || n === 1) { + return 1; + } + + if (!memo.has(n)) { + memo.set(n, this.climbStairs(n - 1, memo) + this.climbStairs(n - 2, memo)); + } + + return memo.get(n); + } + + climbStairs(n) { + const memo = new Map(); + return this.climbStairs(n, memo); + } + } + ``` + + + + + + ```python + class Solution: + def climbStairs(self, n: int) -> int: + memo = {} + return self.helper(n, memo) + + def helper(self, n: int, memo: dict[int, int]) -> int: + if n == 0 or n == 1: + return 1 + if n not in memo: + memo[n] = self.helper(n-1, memo) + self.helper(n-2, memo) + return memo[n] + ``` + + + + ```java + class Solution { + public int climbStairs(int n) { + Map memo = new HashMap<>(); + return climbStairs(n, memo); + } + + private int climbStairs(int n, Map memo) { + if (n == 0 || n == 1) { + return 1; + } + if (!memo.containsKey(n)) { + memo.put(n, climbStairs(n-1, memo) + climbStairs(n-2, memo)); + } + return memo.get(n); + } + } + ``` + + + + + ```cpp + class Solution { + public: + int climbStairs(int n, unordered_map& memo) { + if (n == 0 || n == 1) { + return 1; + } + if (memo.find(n) == memo.end()) { + memo[n] = climbStairs(n-1, memo) + climbStairs(n-2, memo); + } + return memo[n]; + } + + int climbStairs(int n) { + unordered_map memo; + return climbStairs(n, memo); + } + }; + ``` + + + +#### Complexity Analysis + +**Time Complexity:** $O(x * y)$ +- The memoization approach reduces the time complexity to linear by caching previously computed results. + +**Space Complexity:** $O(x * y)$ +- The space complexity is determined by the size of the memoization table. + +Here is the content for the 'Tabulation' and 'Space Optimization' approaches in the 'climb-stair.md' file: + + + +### Approach 3: Tabulation + +The tabulation approach solves the problem iteratively using dynamic programming. It builds a DP table to store the number of ways to reach each step from the base cases (0 and 1 steps) up to the target step. By iterating through the table and filling in values based on the results of previous steps, we compute the total number of ways to climb the stairs. + +#### Implementation + +```javascript +class Solution { + climbStairs(n) { + if (n === 0 || n === 1) { + return 1; + } + + const dp = new Array(n + 1).fill(0); + dp[0] = dp[1] = 1; + + for (let i = 2; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + + return dp[n]; + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + climbStairs(n) { + if (n === 0 || n === 1) { + return 1; + } + + const dp = new Array(n + 1).fill(0); + dp[0] = dp[1] = 1; + + for (let i = 2; i <= n; i++) { + dp[i] = dp[i - 1] + dp[i - 2]; + } + + return dp[n]; + } + } + ``` + + + + ```python + class Solution: + def climbStairs(self, n: int) -> int: + if n == 0 or n == 1: + return 1 + + dp = [0] * (n+1) + dp[0] = dp[1] = 1 + + for i in range(2, n+1): + dp[i] = dp[i-1] + dp[i-2] + return dp[n] + ``` + + + + ```java + class Solution { + public int climbStairs(int n) { + if (n == 0 || n == 1) { + return 1; + } + + int[] dp = new int[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]; + } + } + ``` + + + + ```cpp + class Solution { + public: + int climbStairs(int n) { + if (n == 0 || n == 1) { + return 1; + } + + vector 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]; + } + }; + ``` + + + +#### Complexity Analysis + +**Time Complexity:** $O(n)$ +- The tabulation approach iterates through the DP table once, filling in each cell with constant time operations, resulting in linear time complexity. + +**Space Complexity:** $O(n)$ +- The space complexity is determined by the size of the DP table, which stores values for each step up to the target step. + + + + +### Approach 4: Space Optimization + +The space-optimized approach improves upon the tabulation method by reducing the space complexity. Instead of storing the entire DP table, we only keep track of the previous two values since they are sufficient to compute the current value. By updating these values in each iteration, we compute the total number of ways to climb the stairs with constant space usage. + +#### Implementation + +```javascript +class Solution { + climbStairs(n) { + if (n === 0 || n === 1) { + return 1; + } + + let prev = 1, curr = 1; + for (let i = 2; i <= n; i++) { + let temp = curr; + curr = prev + curr; + prev = temp; + } + + return curr; + } +} +``` + +#### Codes in Different Languages + + + + + ```javascript + class Solution { + climbStairs(n) { + if (n === 0 || n === 1) { + return 1; + } + + let prev = 1, curr = 1; + for (let i = 2; i <= n; i++) { + let temp = curr; + curr = prev + curr; + prev = temp; + } + + return curr; + } +} + ``` + + + + ```python + class Solution: + def climbStairs(self, n: int) -> int: + if n == 0 or n == 1: + return 1 + prev, curr = 1, 1 + for i in range(2, n+1): + temp = curr + curr = prev + curr + prev = temp + return curr + ``` + + + + ```java + class Solution { + public int climbStairs(int n) { + if (n == 0 || n == 1) { + return 1; + } + int prev = 1, curr = 1; + for (int i = 2; i <= n; i++) { + int temp = curr; + curr = prev + curr; + prev = temp; + } + return curr; + } + } + ``` + + + + ```cpp + class Solution { + public: + int climbStairs(int n) { + if (n == 0 || n == 1) { + return 1; + } + int prev = 1, curr = 1; + for (int i = 2; i <= n; i++) { + int temp = curr; + curr = prev + curr; + prev = temp; + } + return curr; + } + }; + ``` + + + +#### Complexity Analysis + +**Time Complexity:** $O(n)$ +- The space-optimized approach iterates through the steps once, updating only two variables in constant time per iteration, resulting in linear time complexity. + +**Space Complexity:** $O(1)$ +- The space complexity is constant since we only use two variables to store the previous two values. + + + +:::tip + +When choosing an approach, consider both time and space complexities. For smaller inputs, simpler approaches like recursion might be sufficient, but for larger inputs, optimized solutions like memoization, tabulation, or space-optimized tabulation are more efficient and practical. Always analyze the constraints and requirements of your problem to select the most appropriate method. + +::: + +--- + +## References + +- **LeetCode Problem**: [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) +- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/maximum-depth-of-binary-tree/solution/) +- **Authors GeeksforGeeks Profile:** [Vipul](https://www.geeksforgeeks.org/user/lakumvipwjge/) \ No newline at end of file From 4978bf1118ab26185bdadfb51ad13b0bbb842bf3 Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Wed, 5 Jun 2024 08:39:45 +0530 Subject: [PATCH 2/3] Climibing Stairs solution added --- .../0010-paths-to-reach-origin.md | 608 ------------------ 1 file changed, 608 deletions(-) delete mode 100644 dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md diff --git a/dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md b/dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md deleted file mode 100644 index e5b69239d..000000000 --- a/dsa-solutions/gfg-solutions/0010-paths-to-reach-origin.md +++ /dev/null @@ -1,608 +0,0 @@ ---- - -id: paths-to-reach-origin -title: Paths to Reach Origin -sidebar_label: 0010 Paths to Reach Origin -tags: -- Dynamic Programming -- Backtracking -- Recursion -- Combinatorics -- JavaScript -- Python -- Java -- C++ -description: "This document explores finding the number of paths to reach the origin (0, 0) on a grid." - ---- - -## Problem Description - -Imagine you are standing on a grid at point (`x`, `y`). You can only move down (y decreases) or right (x increases). Your goal is to reach the origin (0, 0). This document discusses how to find the total number of unique paths you can take to reach the origin. - -### Example - -**Input:** x = 3, y = 2 (Starting at point (3, 2)) - -**Output:** 3 - -There are three unique paths to reach the origin: - -1. Down, Down, Right (D-D-R) -2. Down, Right, Down (D-R-D) -3. Right, Down, Down (R-D-D) - ---- - -## Solutions for Finding Paths - -There are multiple approaches to solve this problem. Here, we will explore four common techniques: - - - - -### Approach 1: Recursive - -A recursive approach solves the problem by breaking down the larger problem into smaller subproblems. - -#### Implementation - -```javascript -class Solution { - ways(x, y) { - return this.help(x, y); - } - - help(i, j) { - // Base case - if (i === 0 && j === 0) return 1; - if (i < 0 || j < 0) return 0; - - // Recursive calls - const down = this.help(i - 1, j); - const right = this.help(i, j - 1); - - return down + right; - } -} -``` - -#### Codes in Different Languages - - - - - ```javascript - class Solution { - ways(x, y) { - return this.help(x, y); - } - - help(i, j) { - // Base case - if (i === 0 && j === 0) return 1; - if (i < 0 || j < 0) return 0; - - // Recursive calls - const down = this.help(i - 1, j); - const right = this.help(i, j - 1); - - return down + right; - } - } - ``` - - - - - - ```python - class Solution: - def ways(self, x, y): - return self.help(x, y) - - def help(self, i, j): - # Base case - if i == 0 and j == 0: - return 1 - if i < 0 or j < 0: - return 0 - - # Recursive calls - down = self.help(i - 1, j) - right = self.help(i, j - 1) - - return down + right - ``` - - - - ```java - class Solution { - public int ways(int x, int y) { - return help(x, y); - } - - private int help(int i, int j) { - // Base case - if (i == 0 && j == 0) return 1; - if (i < 0 || j < 0) return 0; - - // Recursive calls - int down = help(i - 1, j); - int right = help(i, j - 1); - - return down + right; - } - } - ``` - - - - - ```cpp - class Solution { - public: - int ways(int x, int y) { - return help(x, y); - } - - int help(int i, int j) { - // Base case - if (i == 0 && j == 0) return 1; - if (i < 0 || j < 0) return 0; - - // Recursive calls - int down = help(i - 1, j); - int right = help(i, j - 1); - - return down + right; - } - }; - ``` - - - -#### Complexity Analysis - -**Time Complexity:** $O(2^{x+y})$ -- In the worst case, each move (left or down) results in two recursive calls, leading to an exponential number of calls. - -**Space Complexity:** $O(x + y)$ -- The space complexity is due to the maximum depth of the recursion stack. - - - - -### Approach 2: Memoization - -Memoization is an optimization technique where we store the results of expensive function calls and reuse them when the same inputs occur again. - -#### Implementation - -```javascript -class Solution { - constructor() { - this.memo = {}; - } - - ways(x, y) { - return this.help(x, y); - } - - help(i, j) { - // Base case - if (i === 0 && j === 0) return 1; - if (i < 0 || j < 0) return 0; - - const key = `${i},${j}`; - if (this.memo[key] !== undefined) return this.memo[key]; - - // Recursive calls - const down = this.help(i - 1, j); - const right = this.help(i, j - 1); - - this.memo[key] = down + right; - return this.memo[key]; - } -} -``` - -#### Codes in Different Languages - - - - - ```javascript - class Solution { - constructor() { - this.memo = {}; - } - - ways(x, y) { - return this.help(x, y); - } - - help(i, j) { - // Base case - if (i === 0 && j === 0) return 1; - if (i < 0 || j < 0) return 0; - - const key = `${i},${j}`; - if (this.memo[key] !== undefined) return this.memo[key]; - - // Recursive calls - const down = this.help(i - 1, j); - const right = this.help(i, j - 1); - - this.memo[key] = down + right; - return this.memo[key]; - } - } - ``` - - - - - - ```python - class Solution: - def __init__(self): - self.memo = {} - - def ways(self, x, y): - return self.help(x, y) - - def help(self, i, j): - # Base case - if i == 0 and j == 0: - return 1 - if i < 0 or j < 0: - return 0 - - key = (i, j) - if key in self.memo: - return self.memo[key] - - # Recursive calls - down = self.help(i - 1, j) - right = self.help(i, j - 1) - - self.memo[key] = down + right - return self.memo[key] - ``` - - - - - ```java - import java.util.HashMap; - import java.util.Map; - - class Solution { - private Map memo = new HashMap<>(); - - public int ways(int x, int y) { - return help(x, y); - } - - private int help(int i, int j) { - // Base case - if (i == 0 && j == 0) return 1; - if (i < 0 || j < 0) return 0; - - String key = i + "," + j; - if (memo.containsKey(key)) return memo.get(key); - - // Recursive calls - int down = help(i - 1, j); - int right = help(i, j - 1); - - memo.put(key, down + right); - return memo.get(key); - } - } - ``` - - - - ```cpp - #include - #include - using namespace std; - - class Solution { - unordered_map memo; - - public: - int ways(int x, int y) { - return help(x, y); - } - - int help(int i, int j) { - // Base case - if (i == 0 && j == 0) return 1; - if (i < 0 || j < 0) return 0; - - string key = to_string(i) + "," + to_string(j); - if (memo.find(key) != memo.end()) return memo[key]; - - // Recursive calls - int down = help(i - 1, j); - int right = help(i, j - 1); - - memo[key] = down + right; - return - - memo[key]; - } - }; - ``` - - - -#### Complexity Analisys - -**Time Complexity:** $O(x \cdot y)$ -- Each subproblem is solved once and stored in the memoization table. - -**Space Complexity:** $O(x \cdot y)$ -- Space is used for the memoization table. - - - - -### Approach 3: Tabulation - -Tabulation is a bottom-up dynamic programming technique where we solve smaller subproblems first and use their results to build up solutions to larger subproblems. - -#### Implementation - -```javascript -class Solution { - ways(x, y) { - const dp = Array.from({ length: x + 1 }, () => Array(y + 1).fill(0)); - dp[0][0] = 1; - - for (let i = 0; i <= x; i++) { - for (let j = 0; j <= y; j++) { - if (i > 0) dp[i][j] += dp[i - 1][j]; - if (j > 0) dp[i][j] += dp[i][j - 1]; - } - } - - return dp[x][y]; - } -} -``` - -#### Codes in Different Languages - - - - - ```javascript - class Solution { - ways(x, y) { - const dp = Array.from({ length: x + 1 }, () => Array(y + 1).fill(0)); - dp[0][0] = 1; - - for (let i = 0; i <= x; i++) { - for (let j = 0; j <= y; j++) { - if (i > 0) dp[i][j] += dp[i - 1][j]; - if (j > 0) dp[i][j] += dp[i][j - 1]; - } - } - - return dp[x][y]; - } - } - ``` - - - - - ```python - class Solution: - def ways(self, x, y): - dp = [[0] * (y + 1) for _ in range(x + 1)] - dp[0][0] = 1 - - for i in range(x + 1): - for j in range(y + 1): - if i > 0: - dp[i][j] += dp[i - 1][j] - if j > 0: - dp[i][j] += dp[i][j - 1] - - return dp[x][y] - ``` - - - - ```java - class Solution { - public int ways(int x, int y) { - int[][] dp = new int[x + 1][y + 1]; - dp[0][0] = 1; - - for (int i = 0; i <= x; i++) { - for (int j = 0; j <= y; j++) { - if (i > 0) dp[i][j] += dp[i - 1][j]; - if (j > 0) dp[i][j] += dp[i][j - 1]; - } - } - - return dp[x][y]; - } - } - ``` - - - - ```cpp - #include - using namespace std; - - class Solution { - public: - int ways(int x, int y) { - vector> dp(x + 1, vector(y + 1, 0)); - dp[0][0] = 1; - - for (int i = 0; i <= x; i++) { - for (int j = 0; j <= y; j++) { - if (i > 0) dp[i][j] += dp[i - 1][j]; - if (j > 0) dp[i][j] += dp[i][j - 1]; - } - } - - return dp[x][y]; - } - }; - ``` - - - -#### Complexity Analysis - -**Time Complexity:** $O(x \cdot y)$ -- Filling up the table involves computing values for $x \times y$ cells. - -**Space Complexity:** $O(x \cdot y)$ -- Space is used for the 2D table. - - - - -### Approach 4: Space Optimization - -Space optimization improves the efficiency of the tabulation method by reducing the amount of space used. - -#### Implementation - -```javascript -class Solution { - ways(x, y) { - const dp = Array(y + 1).fill(0); - dp[0] = 1; - - for (let i = 0; i <= x; i++) { - for (let j = 1; j <= y; j++) { - dp[j] += dp[j - 1]; - } - } - - return dp[y]; - } -} -``` - -#### Codes in Different Languages - - - - - ```javascript - class Solution { - ways(x, y) { - const dp = Array(y + 1).fill(0); - dp[0] = 1; - - for (let i = 0; i <= x; i++) { - for (let j = 1; j <= y; j++) { - dp[j] += dp[j - 1]; - } - } - - return dp[y]; - } - } - ``` - - - - - ```python - class Solution: - def ways(self, x, y): - dp = [0] * (y + 1) - dp[0] = 1 - - for i in range(x + 1): - for j in range(1, y + 1): - dp[j] += dp[j - 1] - - return dp[y] - ``` - - - - ```java - class Solution { - public int ways(int x, int y) { - int[] dp = new int[y + 1]; - dp[0] = 1; - - for (int i = 0; i <= x; i++) { - for (int j = 1; j <= y; j++) { - dp[j] += dp[j - 1]; - } - } - - return dp[y]; - } - } - ``` - - - - ```cpp - #include - using namespace std; - - class Solution { - public: - int ways(int x, int y) { - vector dp(y + 1, 0); - dp[0] = 1; - - for (int i = 0; i <= x; i++) { - for (int j = 1; j <= y; j++) { - dp[j] += dp[j - 1]; - } - } - - return dp[y]; - } - }; - ``` - - - -#### Complexity Analysis - -**Time Complexity:** $O(x \cdot y)$ -- The same number of computations as in tabulation. - -**Space Complexity:** $O(y)$ -- Only a single array of size $y + 1$ is used. - - - - -:::tip - -When choosing an approach, consider both time and space complexities. For smaller inputs, simpler approaches like recursion might be sufficient, but for larger inputs, optimized solutions like memoization, tabulation, or space-optimized tabulation are more efficient and practical. Always analyze the constraints and requirements of your problem to select the most appropriate method. - -Would you like any additional information or another example? - -::: - ---- - -## References - -- **LeetCode Problem**: [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) -- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/maximum-depth-of-binary-tree/solution/) -- **Authors GeeksforGeeks Profile:** [Vipul](https://www.geeksforgeeks.org/user/lakumvipwjge/) \ No newline at end of file From c9f5b7aef3581b9d1c8fbdeec3c365c12dc43147 Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Wed, 5 Jun 2024 10:10:00 +0530 Subject: [PATCH 3/3] Gray to binary equivalent solution added --- .../0021-gray-to-binary-equivalent.md | 848 ++++++++++++++++++ 1 file changed, 848 insertions(+) create mode 100644 dsa-solutions/gfg-solutions/0021-gray-to-binary-equivalent.md diff --git a/dsa-solutions/gfg-solutions/0021-gray-to-binary-equivalent.md b/dsa-solutions/gfg-solutions/0021-gray-to-binary-equivalent.md new file mode 100644 index 000000000..068a2d2a0 --- /dev/null +++ b/dsa-solutions/gfg-solutions/0021-gray-to-binary-equivalent.md @@ -0,0 +1,848 @@ +--- +id: gray-to-binary-equivalent +title: Gray to Binary Equivalent +sidebar_label: 0021 Gray to Binary Equivalent +tags: + - Bit Manipulation + - Brute Force + - Optimization + - Space Complexity + - Time Complexity + - JavaScript + - TypeScript + - Python + - Java + - C++ +description: "This document explores different approaches to solving the Gray to Binary Equivalent problem, including brute force, bit manipulation, and optimization techniques, in various programming languages." +--- + +## Problem + +Given an integer number `n`, which is a decimal representation of Gray Code, find the binary equivalent of the Gray Code and return the decimal representation of the binary equivalent. + +![table](https://media.geeksforgeeks.org/img-practice/ScreenShot2021-08-27at10-1630039200.png) + +### Example + +**Example 1:** + +``` +Input: +n = 4 + +Output: +7 + +Explanation: +Given 4, its gray code = 110. +Binary equivalent of the gray code 110 is 100. +Return 7 representing gray code 100. +``` + +**Example 2:** + +``` +Input: +n = 15 + +Output: +10 +Explanation: + +Given 15 representing gray code 1000. +Binary equivalent of gray code 1000 is 1111. +Return 10 representing gray code 1111 (binary 1010). +``` + + +**Your Task:** You don't need to read input or print anything. Your task is to complete the function `grayToBinary()` which accepts an integer `n` as an input parameter and returns the decimal representation of the binary equivalent of the given gray code. + +- Expected Time Complexity: $ O(log (n)) $. +- Expected Auxiliary Space: $O(1)$ . + +### Constraints: +- $ 0 <= n <= 10^9$ + +## Solutions + + + + +### Brute Force + + This approach uses brute force by first converting the decimal number to binary and then applying Gray Code logic to find the decimal representation of the binary equivalent. + +#### Implementation +- Convert decimal to binary. +- Apply Gray Code logic to get binary equivalent. +- Convert binary back to decimal. + +```jsx live +function GrayToBinaryBruteForce() { + const decimalInput = 15; // Sample input + + const grayToBinaryBruteForce = function (n) { + let binary = []; + while (n) { + binary.push(n % 2); + n = Math.floor(n / 2); + } + while (binary.length < 32) { + binary.push(0); + } + binary.reverse(); + + let grayCode = []; + let j = 0; + while (binary[j] === 0) { + j++; + } + grayCode[j] = binary[j]; + for (let i = j + 1; i < 32; i++) { + grayCode[i] = grayCode[i - 1] ^ binary[i]; + } + + let grayCodeNum = 0; + for (let i = 31; i >= 0; i--) { + if (grayCode[i]) { + grayCodeNum += Math.pow(2, 31 - i); + } + } + + return grayCodeNum; + }; + + const result = grayToBinaryBruteForce(decimalInput); + + return ( +
+

+ Input: n = {decimalInput} +

+

+ Output: {result} +

+
+ ); +} +``` + +#### Code Snippets + + + + + + ```javascript +class Solution { + decimalToBinary(binary, n) { + while (n) { + if (n % 2) binary.push(1); + else binary.push(0); + n = Math.floor(n / 2); + } + + while (binary.length < 32) binary.push(0); + + binary.reverse(); + } + + help(binary) { + const grayCode = new Array(32).fill(0); + + let j = 0; + while (binary[j] === 0) j++; + + grayCode[j] = binary[j]; + for (let i = j + 1; i < 32; i++) { + grayCode[i] = grayCode[i - 1] ^ binary[i]; + } + + let grayCodeNum = 0; + for (let i = 31; i >= 0; i--) { + if (grayCode[i]) grayCodeNum += 2 ** (31 - i); + } + + return grayCodeNum; + } + + grayToBinary(n) { + const binary = []; + this.decimalToBinary(binary, n); + return this.help(binary); + } +} + + ``` + + + + + ```typescript +class Solution { + decimalToBinary(binary: number[], n: number): void { + while (n) { + if (n % 2) binary.push(1); + else binary.push(0); + n = Math.floor(n / 2); + } + + while (binary.length < 32) binary.push(0); + + binary.reverse(); + } + + help(binary: number[]): number { + const grayCode: number[] = new Array(32).fill(0); + + let j = 0; + while (binary[j] === 0) j++; + + grayCode[j] = binary[j]; + for (let i = j + 1; i < 32; i++) { + grayCode[i] = grayCode[i - 1] ^ binary[i]; + } + + let grayCodeNum = 0; + for (let i = 31; i >= 0; i--) { + if (grayCode[i]) grayCodeNum += 2 ** (31 - i); + } + + return grayCodeNum; + } + + grayToBinary(n: number): number { + const binary: number[] = []; + this.decimalToBinary(binary, n); + return this.help(binary); + } +} + + ``` + + + + + ```cpp +class Solution{ + public: + void decimalToBinary(vector& binary,int n) + { + while(n) + { + if((n%2)) + binary.push_back(1); + else + binary.push_back(0); + + n/=2; + } + + while(binary.size()<32) + binary.push_back(0); + + reverse(binary.begin(),binary.end()); + } + int help(vector& binary) + { + vector grayCode(32,0); + + int j=0; + while(binary[j]==0) + j++; + + grayCode[j]=binary[j]; + for(int i=j+1;i<32;i++) + grayCode[i]=grayCode[i-1]^binary[i]; + + int grayCodeNum=0; + for(int i=31;i>=0;i--) + { + if(grayCode[i]) + grayCodeNum+=pow(2,31-i); + } + return grayCodeNum; + } + int grayToBinary(int n) + { + vector binary; + decimalToBinary(binary,n); + return help(binary); + } +}; + ``` + + + + + ```python +class Solution: + def decimalToBinary(self, binary, n): + while n: + if n % 2: + binary.append(1) + else: + binary.append(0) + n //= 2 + + while len(binary) < 32: + binary.append(0) + + binary.reverse() + + def help(self, binary): + grayCode = [0] * 32 + + j = 0 + while binary[j] == 0: + j += 1 + + grayCode[j] = binary[j] + for i in range(j + 1, 32): + grayCode[i] = grayCode[i - 1] ^ binary[i] + + grayCodeNum = 0 + for i in range(31, -1, -1): + if grayCode[i]: + grayCodeNum += 2 ** (31 - i) + + return grayCodeNum + + def grayToBinary(self, n): + binary = [] + self.decimalToBinary(binary, n) + return self.help(binary) + + ``` + + + + + ```java +import java.util.*; + +class Solution { + void decimalToBinary(ArrayList binary, int n) { + while (n > 0) { + if (n % 2 == 1) binary.add(1); + else binary.add(0); + n /= 2; + } + + while (binary.size() < 32) binary.add(0); + + Collections.reverse(binary); + } + + int help(ArrayList binary) { + int[] grayCode = new int[32]; + + int j = 0; + while (binary.get(j) == 0) j++; + + grayCode[j] = binary.get(j); + for (int i = j + 1; i < 32; i++) { + grayCode[i] = grayCode[i - 1] ^ binary.get(i); + } + + int grayCodeNum = 0; + for (int i = 31; i >= 0; i--) { + if (grayCode[i] == 1) grayCodeNum += Math.pow(2, 31 - i); + } + + return grayCodeNum; + } + + int grayToBinary(int n) { + ArrayList binary = new ArrayList<>(); + decimalToBinary(binary, n); + return help(binary); + } +} + ``` + + + + +#### Complexity Analysis +- Time complexity: O(logN) +- Space complexity: O(32) (constant) + +
+ + + +### Bit Manipulation + + This approach utilizes bit manipulation to directly compute the Gray Code's binary equivalent without converting to binary first. + +#### Implementation + +- Use bit manipulation to apply Gray Code logic directly. + +```jsx live +function GrayToBinaryBitManipulation() { + const decimalInput = 15; // Sample input + + const grayToBinaryBitManipulation = function (n) { + let grayCodeDecimal = 0; + let mask = 0; + let i = 0; + while (n > 0) { + if (i % 2 === 0) { + grayCodeDecimal ^= n; + } else { + mask ^= n; + } + n >>= 1; + i++; + } + grayCodeDecimal ^= mask; + return grayCodeDecimal; + }; + + const result = grayToBinaryBitManipulation(decimalInput); + + return ( +
+

+ Input: n = {decimalInput} +

+

+ Output: {result} +

+
+ ); +} +``` + +#### Code Snippets + + + + + ```javascript +class Solution { + help(n) { + const grayCode = new Array(32).fill(0); + + let j = 0; + while (j <= 31 && (n & (1 << (31 - j))) === 0) { + j++; + } + + grayCode[j] = !!(n & (1 << (31 - j))); + for (let i = j + 1; i < 32; i++) { + const bin = !!(n & (1 << (31 - i))); + const gray = grayCode[i - 1]; + grayCode[i] = bin ^ gray; + } + + let grayCodeDecimal = 0; + for (let i = 31; i >= 0; i--) { + if (grayCode[i]) { + grayCodeDecimal |= (1 << (31 - i)); + } + } + + return grayCodeDecimal; + } + + grayToBinary(n) { + return this.help(n); + } +} + ``` + + + + + ```typescript +class Solution { + help(n: number): number { + const grayCode: number[] = new Array(32).fill(0); + + let j = 0; + while (j <= 31 && (n & (1 << (31 - j))) === 0) { + j++; + } + + grayCode[j] = !!(n & (1 << (31 - j))); + for (let i = j + 1; i < 32; i++) { + const bin = !!(n & (1 << (31 - i))); + const gray = grayCode[i - 1]; + grayCode[i] = bin ^ gray; + } + + let grayCodeDecimal = 0; + for (let i = 31; i >= 0; i--) { + if (grayCode[i]) { + grayCodeDecimal |= (1 << (31 - i)); + } + } + + return grayCodeDecimal; + } + + grayToBinary(n: number): number { + return this.help(n); + } +} + ``` + + + + + ```cpp +class Solution{ + public: + int help(int n) + { + vector grayCode(32,0); + + int j=0; + while(j<=31 and (n&(1<<(31-j)))==0) + j++; + + grayCode[j]=bool(n&(1<<(31-j))); + for(int i=j+1;i<32;i++) + { + int bin=bool(n&(1<<(31-i))); + int gray=grayCode[i-1]; + grayCode[i]=bin^gray; + } + + int grayCodeDecimal=0; + for(int i=31;i>=0;i--) + { + if(grayCode[i]) + grayCodeDecimal|=(1<<31-i); + } + + return grayCodeDecimal; + } + int grayToBinary(int n) + { + return help(n); + } +}; + ``` + + + + + ```python +class Solution: + def help(self, n): + grayCode = [0] * 32 + + j = 0 + while j <= 31 and (n & (1 << (31 - j))) == 0: + j += 1 + + grayCode[j] = bool(n & (1 << (31 - j))) + for i in range(j + 1, 32): + bin_val = bool(n & (1 << (31 - i))) + gray_val = grayCode[i - 1] + grayCode[i] = bin_val ^ gray_val + + grayCodeDecimal = 0 + for i in range(31, -1, -1): + if grayCode[i]: + grayCodeDecimal |= (1 << (31 - i)) + + return grayCodeDecimal + + def grayToBinary(self, n): + return self.help(n) + ``` + + + + + ```java + import java.util.*; + +class Solution { + int help(int n) { + int[] grayCode = new int[32]; + + int j = 0; + while (j <= 31 && (n & (1 << (31 - j))) == 0) { + j++; + } + + grayCode[j] = (n & (1 << (31 - j))) == 0 ? 0 : 1; + for (int i = j + 1; i < 32; i++) { + int bin = (n & (1 << (31 - i))) == 0 ? 0 : 1; + int gray = grayCode[i - 1]; + grayCode[i] = bin ^ gray; + } + + int grayCodeDecimal = 0; + for (int i = 31; i >= 0; i--) { + if (grayCode[i] == 1) { + grayCodeDecimal |= (1 << (31 - i)); + } + } + + return grayCodeDecimal; + } + + int grayToBinary(int n) { + return help(n); + } +} + ``` + + + + +#### Complexity Analysis: +- Time complexity: O(32) (constant) +- Space complexity: O(32) (constant) + +
+ + + +### Optimized + + This approach optimizes the bit manipulation approach by directly calculating the Gray Code's binary equivalent without using extra storage. + +#### Implementation + +- Use bit manipulation without extra storage. + +```jsx live +function GrayToBinaryOptimized() { + const decimalInput = 15; // Sample input + + const grayToBinaryOptimized = function (n) { + let ans = 0; + while (n > 0) { + ans ^= n; + n >>= 1; + } + return ans; + }; + + const result = grayToBinaryOptimized(decimalInput); + + return ( +
+

+ Input: n = {decimalInput} +

+

+ Output: {result} +

+
+ ); +} +``` + + +#### Code Snippets + + + + + ```javascript +class Solution { + help(n) { + const grayCode = new Array(32).fill(0); + + let j = 0; + while (j <= 31 && (n & (1 << (31 - j))) === 0) { + j++; + } + + grayCode[j] = !!(n & (1 << (31 - j))); + for (let i = j + 1; i < 32; i++) { + const bin = !!(n & (1 << (31 - i))); + const gray = grayCode[i - 1]; + grayCode[i] = bin ^ gray; + } + + let grayCodeDecimal = 0; + for (let i = 31; i >= 0; i--) { + if (grayCode[i]) { + grayCodeDecimal |= (1 << (31 - i)); + } + } + + return grayCodeDecimal; + } + + grayToBinary(n) { + return this.help(n); + } +} + ``` + + + + + ```typescript +class Solution { + help(n: number): number { + const grayCode: number[] = new Array(32).fill(0); + + let j = 0; + while (j <= 31 && (n & (1 << (31 - j))) === 0) { + j++; + } + + grayCode[j] = !!(n & (1 << (31 - j))); + for (let i = j + 1; i < 32; i++) { + const bin = !!(n & (1 << (31 - i))); + const gray = grayCode[i - 1]; + grayCode[i] = bin ^ gray; + } + + let grayCodeDecimal = 0; + for (let i = 31; i >= 0; i--) { + if (grayCode[i]) { + grayCodeDecimal |= (1 << (31 - i)); + } + } + + return grayCodeDecimal; + } + + grayToBinary(n: number): number { + return this.help(n); + } +} + ``` + + + + + ```cpp +class Solution{ + public: + int help(int n) + { + vector grayCode(32,0); + + int j=0; + while(j<=31 and (n&(1<<(31-j)))==0) + j++; + + grayCode[j]=bool(n&(1<<(31-j))); + for(int i=j+1;i<32;i++) + { + int bin=bool(n&(1<<(31-i))); + int gray=grayCode[i-1]; + grayCode[i]=bin^gray; + } + + int grayCodeDecimal=0; + for(int i=31;i>=0;i--) + { + if(grayCode[i]) + grayCodeDecimal|=(1<<31-i); + } + + return grayCodeDecimal; + } + int grayToBinary(int n) + { + return help(n); + } +}; + ``` + + + + + ```python + class Solution: + def help(self, n): + grayCode = [0] * 32 + + j = 0 + while j <= 31 and (n & (1 << (31 - j))) == 0: + j += 1 + + grayCode[j] = bool(n & (1 << (31 - j))) + for i in range(j + 1, 32): + bin_val = bool(n & (1 << (31 - i))) + gray_val = grayCode[i - 1] + grayCode[i] = bin_val ^ gray_val + + grayCodeDecimal = 0 + for i in range(31, -1, -1): + if grayCode[i]: + grayCodeDecimal |= (1 << (31 - i)) + + return grayCodeDecimal + + def grayToBinary(self, n): + return self.help(n) + ``` + + + + + ```java +import java.util.*; + +class Solution { + int help(int n) { + int[] grayCode = new int[32]; + + int j = 0; + while (j <= 31 && (n & (1 << (31 - j))) == 0) { + j++; + } + + grayCode[j] = (n & (1 << (31 - j))) == 0 ? 0 : 1; + for (int i = j + 1; i < 32; i++) { + int bin = (n & (1 << (31 - i))) == 0 ? 0 : 1; + int gray = grayCode[i - 1]; + grayCode[i] = bin ^ gray; + } + + int grayCodeDecimal = 0; + for (int i = 31; i >= 0; i--) { + if (grayCode[i] == 1) { + grayCodeDecimal |= (1 << (31 - i)); + } + } + + return grayCodeDecimal; + } + + int grayToBinary(int n) { + return help(n); + } +} + ``` + + + + +#### Complexity Analysis + +- Time complexity: O(32) (constant) +- Space complexity: O(1) (constant) + +
+
+ +:::tip Note + +To convert Gray code to binary efficiently, consider using bit manipulation techniques. Bitwise operations such as XOR (^) can be particularly useful in simplifying the conversion process, leading to optimized solutions with constant time complexity. + +::: + +--- + +## References + +- **LeetCode Problem:** [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) +- **Solution Link:** [Best Time to Buy and Sell Stock Solution on LeetCode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/solutions/) +- **Authors GeeksforGeeks Profile:** [Vipul lakum](https://www.geeksforgeeks.org/user/lakumvipwjge/)