From 90a8589d868da78d7d910cd58ab1925ca856b308 Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Tue, 4 Jun 2024 15:03:44 +0530 Subject: [PATCH 1/5] Balanced Binary Tree solution added --- .../0104-maximum-depth-of-binary-tree.md | 43 ++- .../0100-0199/0110-balanced-binary-tree.md | 256 ++++++++++++++++++ 2 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 dsa-solutions/lc-solutions/0100-0199/0110-balanced-binary-tree.md diff --git a/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md b/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md index 331604352..ef020e41b 100644 --- a/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md +++ b/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md @@ -45,7 +45,6 @@ Output: 2 ## Solution for Maximum Depth of Binary Tree Problem - @@ -62,6 +61,45 @@ To find the maximum depth of a binary tree, we can use a depth-first search (DFS 3. Recursively find the maximum depth of the left and right subtrees. 4. Return the maximum of the left and right subtree depths plus one. +#### Implementation + +```jsx live +function MaxDepthOfBinaryTree() { + class TreeNode { + constructor(val = 0, left = null, right = null) { + this.val = val; + this.left = left; + this.right = right; + } + } + + const maxDepth = function (root) { + if (!root) return 0; + const leftDepth = maxDepth(root.left); + const rightDepth = maxDepth(root.right); + return Math.max(leftDepth, rightDepth) + 1; + }; + + const root = new TreeNode(3); + root.left = new TreeNode(9); + root.right = new TreeNode(20); + root.right.left = new TreeNode(15); + root.right.right = new TreeNode(7); + + const result = maxDepth(root); + return ( +
+

+ Input: root = [3,9,20,null,null,15,7] +

+

+ Output: {result} +

+
+ ); +} +``` + #### Code in Different Languages @@ -220,4 +258,5 @@ Another approach to find the maximum depth of a binary tree is to use breadth-fi - **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 lakum](https://leetcode.com/u/vipul_lakum_02/) ---- \ No newline at end of file + +--- diff --git a/dsa-solutions/lc-solutions/0100-0199/0110-balanced-binary-tree.md b/dsa-solutions/lc-solutions/0100-0199/0110-balanced-binary-tree.md new file mode 100644 index 000000000..7556e0245 --- /dev/null +++ b/dsa-solutions/lc-solutions/0100-0199/0110-balanced-binary-tree.md @@ -0,0 +1,256 @@ +--- +id: balanced-binary-tree +title: Balanced Binary Tree Solution +sidebar_label: 0110 Balanced Binary Tree +tags: + - Binary Tree + - Depth-First Search + - Recursion + - LeetCode + - C++ + - Java + - Python +description: "This is a solution to the Balanced Binary Tree problem on LeetCode." +--- + +## Problem Description + +Given a binary tree, determine if it is height-balanced. + +A height-balanced binary tree is defined as: + +- A binary tree in which the left and right subtrees of every node differ in height by no more than 1. + +### Examples + +**Example 1:** + +![input Tree](https://assets.leetcode.com/uploads/2020/10/06/balance_1.jpg) + +``` +Input: root = [3,9,20,null,null,15,7] +Output: true +``` + +**Example 2:** + +![input Tree](https://assets.leetcode.com/uploads/2020/10/06/balance_2.jpg) +``` +Input: root = [1,2,2,3,3,null,null,4,4] +Output: false +``` + +**Example 3:** + +``` +Input: root = [] +Output: true +``` + +### Constraints + +- The number of nodes in the tree is in the range `[0, 5000]`. +- $ -10^4 <=$ Node.val $<= 10^4 $ + +--- + +## Solution for Balanced Binary Tree Problem + + + + +### Approach 1: Top-Down + +#### Intuition + +This method checks whether the tree is balanced strictly according to the definition of a balanced binary tree: the difference between the heights of the two subtrees is not greater than 1, and both the left and right subtrees are also balanced. With the helper function depth(), we can easily write the code. + +#### Implementation + +Implement a helper function `depth(root)` that returns the depth of the tree rooted at root. +Check if the absolute difference between the depths of the left and right subtrees is not greater than 1. +Recursively check if both the left and right subtrees are balanced. +Return true if the tree is balanced, otherwise return false. + +#### Code in Different Languages + + + + + ```java + class Solution { + public int depth(TreeNode root) { + if (root == null) return 0; + return Math.max(depth(root.left), depth(root.right)) + 1; + } + + public boolean isBalanced(TreeNode root) { + if (root == null) return true; + + int left = depth(root.left); + int right = depth(root.right); + + return Math.abs(left - right) <= 1 && isBalanced(root.left) && isBalanced(root.right); + } + } + ``` + + + + + ```python + class Solution: + def depth(self, root: TreeNode) -> int: + if root is None: + return 0 + return max(self.depth(root.left), self.depth(root.right)) + 1 + + def isBalanced(self, root: TreeNode) -> bool: + if root is None: + return True + + left = self.depth(root.left) + right = self.depth(root.right) + + return abs(left - right) <= 1 and self.isBalanced(root.left) and self.isBalanced(root.right) + ``` + + + + + ```cpp + class Solution { + public: + int depth(TreeNode* root) { + if (root == nullptr) return 0; + return max(depth(root->left), depth(root->right)) + 1; + } + + bool isBalanced(TreeNode* root) { + if (root == nullptr) return true; + + int left = depth(root->left); + int right = depth(root->right); + + return abs(left - right) <= 1 && isBalanced(root->left) && isBalanced(root->right); + } + }; + ``` + + + + +#### Complexity Analysis + +- **Time Complexity**: O(n log n) in the worst case where n is the number of nodes in the tree. We visit each node once, and for each node, we calculate its depth. Since the depth calculation involves traversing the subtree, the overall time complexity is O(n log n). +- **Space Complexity**: O(n) for the recursive call stack. + + + + +### Approach 2: Bottom-Up + +#### Intuition + +The second method is based on DFS. Instead of calling depth() explicitly for each child node, we return the height of the current node in DFS recursion. When the subtree of the current node (inclusive) is balanced, the function dfsHeight() returns a non-negative value as the height. Otherwise, -1 is returned. According to the left height and right height of the two children, the parent node could check if the subtree is balanced and decide its return value. + +#### Implementation + +Implement a helper function dfsHeight(root) that returns the height of the tree rooted at root. +If the subtree rooted at root is balanced, return its height. Otherwise, return -1. +Check if the returned height is -1 to determine if the tree is balanced. + +#### Code in Different Languages + + + + + ```java + class Solution { + public int dfsHeight(TreeNode root) { + if (root == null) return 0; + + int leftHeight = dfsHeight(root.left); + if (leftHeight == -1) return -1; + int rightHeight = dfsHeight(root.right); + if (rightHeight == -1) return -1; + + if (Math.abs(leftHeight - rightHeight) > 1) return -1; + return Math.max(leftHeight, rightHeight) + 1; + } + + public boolean isBalanced(TreeNode root) { + return dfsHeight(root) != -1; + } + } + ``` + + + + + ```python + class Solution: + def dfsHeight(self, root: TreeNode) -> int: + if root is None: + return 0 + + leftHeight = self.dfsHeight(root.left) + if leftHeight == -1: + return -1 + right + + Height = self.dfsHeight(root.right) + if rightHeight == -1: + return -1 + + if abs(leftHeight - rightHeight) > 1: + return -1 + return max(leftHeight, rightHeight) + 1 + + def isBalanced(self, root: TreeNode) -> bool: + return self.dfsHeight(root) != -1 + ``` + + + + + ```cpp + class Solution { + public: + int dfsHeight(TreeNode* root) { + if (root == nullptr) return 0; + + int leftHeight = dfsHeight(root->left); + if (leftHeight == -1) return -1; + int rightHeight = dfsHeight(root->right); + if (rightHeight == -1) return -1; + + if (abs(leftHeight - rightHeight) > 1) return -1; + return max(leftHeight, rightHeight) + 1; + } + + bool isBalanced(TreeNode* root) { + return dfsHeight(root) != -1; + } + }; + ``` + + + + +#### Complexity Analysis + +- **Time Complexity**: O(n) in the worst case where n is the number of nodes in the tree. Each node is visited once. +- **Space Complexity**: O(n) for the recursive call stack. + + + + +## References + +- **LeetCode Problem**: [Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) +- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/balanced-binary-tree/solution/) +- **Authors GeeksforGeeks Profile:** [Vipul lakum](https://leetcode.com/u/vipul_lakum_02/) + + +--- From bb3cf7985fa3ecfc4cbe1fec34395ae389e5e58f Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Tue, 4 Jun 2024 16:08:16 +0530 Subject: [PATCH 2/5] valid palindrome added --- .../0104-maximum-depth-of-binary-tree.md | 4 + .../0100-0199/0125-valid-palindrome.md | 134 ++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md diff --git a/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md b/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md index ef020e41b..520338554 100644 --- a/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md +++ b/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md @@ -166,6 +166,10 @@ Another approach to find the maximum depth of a binary tree is to use breadth-fi - Push all the children of the current level into the queue. 4. Return `depth` after traversing all levels. +#### Implementation + + + #### Code in Different Languages diff --git a/dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md b/dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md new file mode 100644 index 000000000..2ded85933 --- /dev/null +++ b/dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md @@ -0,0 +1,134 @@ +--- +id: valid-palindrome +title: Valid Palindrome Solution +sidebar_label: 0125 Valid Palindrome +tags: + - String + - Two Pointers + - LeetCode + - Java + - Python +description: "This is a solution to the Valid Palindrome problem on LeetCode." +--- + +## Problem Description + +A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers. + +Given a string s, return true if it is a palindrome, or false otherwise. + +### Examples + +**Example 1:** + +``` +Input: s = "A man, a plan, a canal: Panama" +Output: true +Explanation: "amanaplanacanalpanama" is a palindrome. +``` + +**Example 2:** + +``` +Input: s = "race a car" +Output: false +Explanation: "raceacar" is not a palindrome. +``` + +**Example 3:** + +``` +Input: s = " " +Output: true +Explanation: s is an empty string "" after removing non-alphanumeric characters. +Since an empty string reads the same forward and backward, it is a palindrome. +``` + +### Constraints + +- $ (1 <= s.length <= 2 * 10^5) $ +- `s` consists only of printable ASCII characters. + +--- + +## Solution for Valid Palindrome Problem + +### Approach + +This code is an implementation of a solution to determine if a given string is a palindrome. A string is considered a palindrome if it reads the same forwards and backwards, ignoring spaces, punctuation, and letter casing. + +The approach used in this solution is a two-pointer technique, where two pointers are maintained, one at the start of the string and the other at the end of the string. The two pointers move towards each other until they meet in the middle of the string. + +At each iteration of the while loop, the characters pointed to by the start and last pointers are checked. If either of the characters is not a letter or digit (e.g., a space or punctuation), the pointer is moved one step to the right (for start) or one step to the left (for last) until a letter or digit is found. + +If both characters are letters or digits, they are converted to lowercase and compared. If they are not equal, the function returns false, as the string is not a palindrome. If they are equal, both pointers are moved one step to the right and left, respectively. + +The while loop continues until the start pointer is greater than the last pointer, indicating that all the characters have been checked and that the string is a palindrome. The function then returns true. + +### Complexity + +- Time Complexity: O(n), where n is the length of the string. This is because, in the worst case, all characters in the string need to be checked once, so the number of operations is proportional to the length of the string. +- Space Complexity: O(1), as no additional data structures are used, and only a constant amount of memory is required for the start and last pointers and a few variables. + +### Code + +#### Java + +```java +class Solution { + public boolean isPalindrome(String s) { + if (s.isEmpty()) { + return true; + } + int start = 0; + int last = s.length() - 1; + while(start <= last) { + char currFirst = s.charAt(start); + char currLast = s.charAt(last); + if (!Character.isLetterOrDigit(currFirst)) { + start++; + } else if (!Character.isLetterOrDigit(currLast)) { + last--; + } else { + if (Character.toLowerCase(currFirst) != Character.toLowerCase(currLast)) { + return false; + } + start++; + last--; + } + } + return true; + } +} +``` + +#### Python + +```python +class Solution: + def isPalindrome(self, s: str) -> bool: + if not s: + return True + start = 0 + last = len(s) - 1 + while start <= last: + curr_first = s[start] + curr_last = s[last] + if not curr_first.isalnum(): + start += 1 + elif not curr_last.isalnum(): + last -= 1 + else: + if curr_first.lower() != curr_last.lower(): + return False + start += 1 + last -= 1 + return True +``` + +--- + +## References + +- **LeetCode Problem**: [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) +- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/valid-palindrome/solution/) \ No newline at end of file From 538929c0bba1441b0ef1ce926b2262e7e4dcc1ce Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Tue, 4 Jun 2024 17:36:17 +0530 Subject: [PATCH 3/5] valid palindrome added --- .../0104-maximum-depth-of-binary-tree.md | 142 +++++++ .../0100-0199/0125-valid-palindrome.md | 357 ++++++++++++++---- 2 files changed, 423 insertions(+), 76 deletions(-) diff --git a/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md b/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md index 520338554..50ca3528e 100644 --- a/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md +++ b/dsa-solutions/lc-solutions/0100-0199/0104-maximum-depth-of-binary-tree.md @@ -103,6 +103,41 @@ function MaxDepthOfBinaryTree() { #### Code in Different Languages + + + ```javascript + function maxDepth(root) { + if (!root) return 0; + const maxLeft = maxDepth(root.left); + const maxRight = maxDepth(root.right); + return Math.max(maxLeft, maxRight) + 1; + } + ``` + + + + + ```typescript + class TreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + constructor(val: number) { + this.val = val; + this.left = null; + this.right = null; + } + } + + function maxDepth(root: TreeNode | null): number { + if (!root) return 0; + const maxLeft: number = maxDepth(root.left); + const maxRight: number = maxDepth(root.right); + return Math.max(maxLeft, maxRight) + 1; + } + ``` + + ```java @@ -168,11 +203,118 @@ Another approach to find the maximum depth of a binary tree is to use breadth-fi #### Implementation +```jsx live +function MaxDepthOfBinaryTree() { + class TreeNode { + constructor(val) { + this.val = val; + this.left = null; + this.right = null; + } + } + // Creating the binary tree + const root = new TreeNode(3); + root.left = new TreeNode(9); + root.right = new TreeNode(20); + root.right.left = new TreeNode(15); + root.right.right = new TreeNode(7); + + const maxDepth = function (root) { + if (!root) return 0; + + let depth = 0; + const queue = [root]; + + while (queue.length) { + const size = queue.length; + for (let i = 0; i < size; i++) { + const node = queue.shift(); + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + depth++; + } + + return depth; + }; + + const result = maxDepth(root); + return ( +
+

+ Binary Tree: {JSON.stringify(root)} +

+

+ Maximum Depth: {result} +

+
+ ); +} +``` #### Code in Different Languages + + + ```javascript + function maxDepth(root) { + if (!root) return 0; + + let depth = 0; + const queue = [root]; + + while (queue.length) { + depth++; + const levelSize = queue.length; + for (let i = 0; i < levelSize; ++i) { + const node = queue.shift(); + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + } + + return depth; + } + ``` + + + + + ```typescript + class TreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + constructor(val: number) { + this.val = val; + this.left = null; + this.right = null; + } + } + + function maxDepth(root: TreeNode | null): number { + if (!root) return 0; + + let depth = 0; + const queue: TreeNode[] = [root]; + + while (queue.length) { + depth++; + const levelSize = queue.length; + for (let i = 0; i < levelSize; ++i) { + const node = queue.shift()!; + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + } + + return depth; + } + ``` + + ```java diff --git a/dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md b/dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md index 2ded85933..466830035 100644 --- a/dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md +++ b/dsa-solutions/lc-solutions/0100-0199/0125-valid-palindrome.md @@ -4,25 +4,24 @@ title: Valid Palindrome Solution sidebar_label: 0125 Valid Palindrome tags: - String - - Two Pointers + - Two Pointer - LeetCode - - Java - Python + - Java + - C++ description: "This is a solution to the Valid Palindrome problem on LeetCode." --- ## Problem Description -A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers. - -Given a string s, return true if it is a palindrome, or false otherwise. +Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. ### Examples **Example 1:** ``` -Input: s = "A man, a plan, a canal: Panama" +Input: "A man, a plan, a canal: Panama" Output: true Explanation: "amanaplanacanalpanama" is a palindrome. ``` @@ -30,105 +29,311 @@ Explanation: "amanaplanacanalpanama" is a palindrome. **Example 2:** ``` -Input: s = "race a car" +Input: "race a car" Output: false Explanation: "raceacar" is not a palindrome. ``` -**Example 3:** +### Constraints -``` -Input: s = " " -Output: true -Explanation: s is an empty string "" after removing non-alphanumeric characters. -Since an empty string reads the same forward and backward, it is a palindrome. -``` +- The input string may consist of uppercase and lowercase letters, digits, and punctuation symbols. +- The empty string is considered a valid palindrome. -### Constraints +## Solution for Valid Palindrome Problem -- $ (1 <= s.length <= 2 * 10^5) $ -- `s` consists only of printable ASCII characters. + + + +### Approach 1: Brute Force ---- +#### Intuition -## Solution for Valid Palindrome Problem +The brute force approach involves stripping non-alphanumeric characters from the string and then checking if the resulting string is a palindrome by comparing it with its reverse. -### Approach +#### Implementation -This code is an implementation of a solution to determine if a given string is a palindrome. A string is considered a palindrome if it reads the same forwards and backwards, ignoring spaces, punctuation, and letter casing. +```jsx live +function ValidPalindromeTwoPointer() { + const isPalindrome = function (s) { + if (!s) return true; + let left = 0, + right = s.length - 1; + while (left < right) { + while (left < right && !s[left].match(/[a-zA-Z0-9]/)) left++; + while (left < right && !s[right].match(/[a-zA-Z0-9]/)) right--; + if (s[left].toLowerCase() !== s[right].toLowerCase()) return false; + left++; + right--; + } + return true; + }; -The approach used in this solution is a two-pointer technique, where two pointers are maintained, one at the start of the string and the other at the end of the string. The two pointers move towards each other until they meet in the middle of the string. + const input = "A man, a plan, a canal: Panama"; + const output = isPalindrome(input); -At each iteration of the while loop, the characters pointed to by the start and last pointers are checked. If either of the characters is not a letter or digit (e.g., a space or punctuation), the pointer is moved one step to the right (for start) or one step to the left (for last) until a letter or digit is found. + return ( +
+

+ Input: {input} +

+

+ Output: {output.toString()} +

+
+ ); +} +``` -If both characters are letters or digits, they are converted to lowercase and compared. If they are not equal, the function returns false, as the string is not a palindrome. If they are equal, both pointers are moved one step to the right and left, respectively. +#### Code in Different Languages -The while loop continues until the start pointer is greater than the last pointer, indicating that all the characters have been checked and that the string is a palindrome. The function then returns true. + + + + ```javascript + function isPalindrome(s) { + if (!s) return true; + const cleanedS = s.replace(/[^A-Za-z0-9]/g, '').toLowerCase(); + return cleanedS === cleanedS.split('').reverse().join(''); + } + ``` -### Complexity + + + + ```typescript + function isPalindrome(s: string): boolean { + if (!s) return true; + const cleanedS = s.replace(/[^A-Za-z0-9]/g, '').toLowerCase(); + return cleanedS === cleanedS.split('').reverse().join(''); + } -- Time Complexity: O(n), where n is the length of the string. This is because, in the worst case, all characters in the string need to be checked once, so the number of operations is proportional to the length of the string. -- Space Complexity: O(1), as no additional data structures are used, and only a constant amount of memory is required for the start and last pointers and a few variables. + const input: string = "A man, a plan, a canal: Panama"; + const output: boolean = isPalindrome(input); -### Code + console.log("Input:", input); + console.log("Output:", output); + ``` -#### Java + + + + ```python + def is_palindrome(s: str) -> bool: + if not s: + return True + cleaned_s = ''.join(ch.lower() for ch in s if ch.isalnum()) + return cleaned_s == cleaned_s[::-1] -```java -class Solution { - public boolean isPalindrome(String s) { - if (s.isEmpty()) { - return true; + input_str = "A man, a plan, a canal: Panama" + output = is_palindrome(input_str) + + print("Input:", input_str) + print("Output:", output) + + ``` + + + + + ```java + class Solution { + public boolean isPalindrome(String s) { + if (s == null || s.isEmpty()) { + return true; + } + + String cleanedS = s.replaceAll("[^A-Za-z0-9]", "").toLowerCase(); + return cleanedS.equals(new StringBuilder(cleanedS).reverse().toString()); } - int start = 0; - int last = s.length() - 1; - while(start <= last) { - char currFirst = s.charAt(start); - char currLast = s.charAt(last); - if (!Character.isLetterOrDigit(currFirst)) { - start++; - } else if (!Character.isLetterOrDigit(currLast)) { - last--; - } else { - if (Character.toLowerCase(currFirst) != Character.toLowerCase(currLast)) { - return false; + } + ``` + + + + + ```cpp + class Solution { + public: + bool isPalindrome(string s) { + if (s.empty()) { + return true; + } + + string cleanedS; + for (char ch : s) { + if (isalnum(ch)) { + cleanedS += tolower(ch); } - start++; - last--; } + + string reversedS = cleanedS; + reverse(reversedS.begin(), reversedS.end()); + + return cleanedS == reversedS; } - return true; - } + }; + ``` + + + + +#### Complexity Analysis + +- Time Complexity: O(n), where n is the length of the input string. We iterate through the string once. +- Space Complexity: O(n), where n is the length of the input string. We create a new string to store the cleaned version of the input. + +
+ + +### Approach 2: Two Pointer + +#### Intuition + +The two-pointer approach involves using two pointers, one starting from the beginning of the string and the other starting from the end. We move both pointers towards the center of the string, comparing characters at each step until they meet or cross each other. + +#### Implementation + +```jsx live +function ValidPalindromeBruteForce() { + const isPalindrome = function (s) { + if (!s) return true; + const cleanedS = s.replace(/[^A-Za-z0-9]/g, "").toLowerCase(); + return cleanedS === cleanedS.split("").reverse().join(""); + }; + + const input = "A man, a plan, a canal: Panama"; + const output = isPalindrome(input); + + return ( +
+

+ Input: {input} +

+

+ Output: {output.toString()} +

+
+ ); } ``` -#### Python - -```python -class Solution: - def isPalindrome(self, s: str) -> bool: - if not s: - return True - start = 0 - last = len(s) - 1 - while start <= last: - curr_first = s[start] - curr_last = s[last] - if not curr_first.isalnum(): - start += 1 - elif not curr_last.isalnum(): - last -= 1 - else: - if curr_first.lower() != curr_last.lower(): - return False - start += 1 - last -= 1 - return True -``` +#### Code in Different Languages ---- + + + + ```javascript + function isPalindrome(s) { + if (!s) return true; + let left = 0, right = s.length - 1; + while (left < right) { + while (left < right && !s[left].match(/[a-zA-Z0-9]/)) left++; + while (left < right && !s[right].match(/[a-zA-Z0-9]/)) right--; + if (s[left].toLowerCase() !== s[right].toLowerCase()) return false; + left++; + right--; + } + return true; + } + ``` + + + + + ```typescript + function isPalindrome(s: string): boolean { + if (!s) return true; + let left = 0, right = s.length - 1; + while (left < right) { + while (left < right && !s[left].match(/[a-zA-Z0-9]/)) left++; + while (left < right && !s[right].match(/[a-zA-Z0-9]/)) right--; + if (s[left].toLowerCase() !== s[right].toLowerCase()) return false; + left++; + right--; + } + return true; + } + ``` + + + + + ```java + class Solution { + public boolean isPalindrome(String s) { + if (s == null || s.isEmpty()) { + return true; + } + + int left = 0, right = s.length() - 1; + while (left < right) { + while (left < right && !Character.isLetterOrDigit(s.charAt(left))) left++; + while (left < right && !Character.isLetterOrDigit(s.charAt(right))) right--; + if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) return false; + left++; + right--; + } + return true; + } + } + ``` + + + + + ```python + def is_palindrome(s: str) -> bool: + if not s: + return True + left, right = 0, len(s) - 1 + while left < right: + while left < right and not s[left].isalnum(): left += 1 + while left < right and not s[right].isalnum(): right -= 1 + if s[left].lower() != s[right].lower(): return False + left += 1 + right -= 1 + return True + ``` + + + + + ```cpp + class Solution { + public: + bool isPalindrome(string s) { + if (s.empty()) { + return true; + } + + int left = 0, right = s.length() - 1; + while (left < right) { + while (left < right && !isalnum(s[left])) left++; + while (left < right && !isalnum(s[right])) right--; + if (tolower(s[left]) != tolower(s[right])) return false; + left++; + right--; + } + return true; + } + }; + ``` + + + + +#### Complexity Analysis + +- Time Complexity: O(n), where n is the length of the input string. We iterate through the string once. +- Space Complexity: O(1). We're not using any extra space. + +
+
## References - **LeetCode Problem**: [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) -- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/valid-palindrome/solution/) \ No newline at end of file + +- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/valid-palindrome/solution/) + +- **Authors GeeksforGeeks Profile:** [Vipul lakum](https://leetcode.com/u/vipul_lakum_02/) From 9e03916c160eabe0b8cb0617820396c4c345f31f Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Tue, 4 Jun 2024 19:03:51 +0530 Subject: [PATCH 4/5] Binary tree level order traversal solution added --- .../0102-binary-tree-level-order-traversal.md | 520 ++++++++++++++++++ 1 file changed, 520 insertions(+) create mode 100644 dsa-solutions/lc-solutions/0100-0199/0102-binary-tree-level-order-traversal.md diff --git a/dsa-solutions/lc-solutions/0100-0199/0102-binary-tree-level-order-traversal.md b/dsa-solutions/lc-solutions/0100-0199/0102-binary-tree-level-order-traversal.md new file mode 100644 index 000000000..e2561902b --- /dev/null +++ b/dsa-solutions/lc-solutions/0100-0199/0102-binary-tree-level-order-traversal.md @@ -0,0 +1,520 @@ +--- +id: binary-tree-level-order-traversal +title: Binary Tree Level Order Traversal Solution +sidebar_label: 0102 Binary Tree Level Order Traversal +tags: + - Tree + - Breadth First Search + - Queue + - LeetCode + - Python + - Java + - C++ +description: "This is a solution to the Binary Tree Level Order Traversal problem on LeetCode." +--- + +## Problem Description + +Given the root of a binary tree, return the level order traversal of its nodes' values. (i.e., from left to right, level by level). + +### Examples + +**Example 1:** + +![input Tree](https://assets.leetcode.com/uploads/2021/02/19/tree1.jpg) +``` +Input: root = [3,9,20,null,null,15,7] +Output: [[3],[9,20],[15,7]] +``` + +**Example 2:** + +``` +Input: root = [1] +Output: [[1]] +``` + +**Example 3:** + +``` +Input: root = [] +Output: [] +``` + +**Constraints:** + +- The number of nodes in the tree is in the range [0, 2000]. +- $ -1000 <= $ Node.val $ <= 1000 $ + +## Solution for Binary Tree Level Order Traversal Problem + +### Intuition + +To perform a level-order traversal on a binary tree and store the nodes’ values in a 2D vector representing each level, start by initialising an empty queue to hold the level by level nodes. Enqueue the root node into the queue and traverse until the queue is empty. For each level, track the number of nodes in that level, creating a temporary vector to deque and store them. At each node, store its value in the temporary vector and enqueue its left and right children if they exist. Once all the nodes at a level are processed add this 1D temporary vector to the final 2D vector, representing that level. This process repeats until all levels are traversed. Finally, return this 2D vector containing the level order traversal of the binary tree. + +### Algorithm: + +**Step 1:** Initialise an empty queue data structure to store the nodes during traversal. Create a 2D array or a vector of a vector to store the level order traversal. If the tree is empty, return this empty 2D vector. + +**Step 2:** Enqueue the root node i.e. Add the root node of the binary tree to the queue. + +**Step 3:** + +Iterate until the queue is empty: + +- Get the current size of the queue. This size indicates the number of nodes at the current level. +- Create a vector ‘level’ to store the nodes at the current level. +- Iterate through ‘size’ number of nodes at the current level: + - Pop the front node from the queue. + - Store the node’s value in the level vector. + - Enqueue the left and right child nodes of the current node (if they exist) into the queue. +- After processing all the nodes at the current level, add the ‘level’ vector to the ‘ans’ 2D vector, representing the current level. + +**Step 4:** Once the traversal loop completes i.e. all levels have been processed, return the ‘ans’ 2D vector containing the level-order traversal. + +### Code in Different Languages + + + + + ```cpp + #include + #include + #include + + using namespace std; + + // TreeNode struct represents + // a node in a binary tree + struct TreeNode { + int val; + TreeNode* left; + TreeNode* right; + + // Default constructor for TreeNode + TreeNode() : val(0), left(nullptr), right(nullptr) {} + + // Constructor with a value + // parameter for TreeNode + TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + + // Constructor with value, left + // child, and right child + // parameters for TreeNode + TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {} + }; + + + class Solution { + public: + // Function to perform level-order + // traversal of a binary tree + vector> levelOrder(TreeNode* root) { + // Create a 2D vector to store levels + vector> ans; + if (root == nullptr) { + // If the tree is empty, + // return an empty vector + return ans; + } + + // Create a queue to store nodes + // for level-order traversal + queue q; + // Push the root node to the queue + q.push(root); + + while (!q.empty()) { + // Get the size of the current level + int size = q.size(); + // Create a vector to store + // nodes at the current level + vector level; + + for (int i = 0; i < size; i++) { + // Get the front node in the queue + TreeNode* node = q.front(); + // Remove the front node from the queue + q.pop(); + // Store the node value + // in the current level vector + level.push_back(node->val); + + // Enqueue the child nodes if they exist + if (node->left != nullptr) { + q.push(node->left); + } + if (node->right != nullptr) { + q.push(node->right); + } + } + // Store the current level + // in the answer vector + ans.push_back(level); + } + // Return the level-order + // traversal of the tree + return ans; + } + }; + + // Function to print + // the elements of a vector + void printVector(const vector& vec) { + // Iterate through the + // vector and print each element + for (int num : vec) { + cout << num << " "; + } + cout << endl; + } + + // Main function + int main() { + // Creating a sample binary tree + TreeNode* root = new TreeNode(1); + root->left = new TreeNode(2); + root->right = new TreeNode(3); + root->left->left = new TreeNode(4); + root->left->right = new TreeNode(5); + + // Create an instance + // of the Solution class + Solution solution; + // Perform level-order traversal + vector> result = solution.levelOrder(root); + + cout << "Level Order Traversal of Tree: "<< endl; + + // Printing the level order traversal result + for (const vector& level : result) { + printVector(level); + } + + return 0; + } + ``` + + + + + + ``` + #include + #include + #include + + using namespace std; + + // TreeNode struct represents + // a node in a binary tree + struct TreeNode { + int val; + TreeNode* left; + TreeNode* right; + + // Default constructor for TreeNode + TreeNode() : val(0), left(nullptr), right(nullptr) {} + + // Constructor with a value + // parameter for TreeNode + TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + + // Constructor with value, left + // child, and right child + // parameters for TreeNode + TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {} + }; + + + class Solution { + public: + // Function to perform level-order + // traversal of a binary tree + vector> levelOrder(TreeNode* root) { + // Create a 2D vector to store levels + vector> ans; + if (root == nullptr) { + // If the tree is empty, + // return an empty vector + return ans; + } + + // Create a queue to store nodes + // for level-order traversal + queue q; + // Push the root node to the queue + q.push(root); + + while (!q.empty()) { + // Get the size of the current level + int size = q.size(); + // Create a vector to store + // nodes at the current level + vector level; + + for (int i = 0; i < size; i++) { + // Get the front node in the queue + TreeNode* node = q.front(); + // Remove the front node from the queue + q.pop(); + // Store the node value + // in the current level vector + level.push_back(node->val); + + // Enqueue the child nodes if they exist + if (node->left != nullptr) { + q.push(node->left); + } + if (node->right != nullptr) { + q.push(node->right); + } + } + // Store the current level + // in the answer vector + ans.push_back(level); + } + // Return the level-order + // traversal of the tree + return ans; + } + }; + + // Function to print + // the elements of a vector + void printVector(const vector& vec) { + // Iterate through the + // vector and print each element + for (int num : vec) { + cout << num << " "; + } + cout << endl; + } + + // Main function + int main() { + // Creating a sample binary tree + TreeNode* root = new TreeNode(1); + root->left = new TreeNode(2); + root->right = new TreeNode(3); + root->left->left = new TreeNode(4); + root->left->right = new TreeNode(5); + + // Create an instance + // of the Solution class + Solution solution; + // Perform level-order traversal + vector> result = solution.levelOrder(root); + + cout << "Level Order Traversal of Tree: "<< endl; + + // Printing the level order traversal result + for (const vector& level : result) { + printVector(level); + } + + return 0; + } + ``` + + + + + + ``` + from collections import deque + + # TreeNode class represents + # a node in a binary tree + class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + class Solution: + def levelOrder(self, root): + # Create a list to store levels + ans = [] + if not root: + # If the tree is empty, + # return an empty list + return ans + + # Create a queue to store nodes + # for level-order traversal + q = deque() + # Enqueue the root node + q.append(root) + + while q: + # Get the size of the current level + size = len(q) + # Create a list to store + # nodes at the current level + level = [] + + for i in range(size): + # Get the front node in the queue + node = q.popleft() + # Store the node value + # in the current level list + level.append(node.val) + + # Enqueue the child nodes if they exist + if node.left: + q.append(node.left) + if node.right: + q.append(node.right) + + # Store the current level + # in the answer list + ans.append(level) + # Return the level-order + # traversal of the tree + return ans + + # Function to print + # the elements of a list + def printList(lst): + # Iterate through the + # list and print each element + for num in lst: + print(num, end=" ") + print() + + # Main function + if __name__ == "__main__": + # Creating a sample binary tree + root = TreeNode(1) + root.left = TreeNode(2) + root.right = TreeNode(3) + root.left.left = TreeNode(4) + root.left.right = TreeNode(5) + + # Create an instance + # of the Solution class + solution = Solution() + # Perform level-order traversal + result = solution.levelOrder(root) + + print("Level Order Traversal of Tree:") + + # Printing the level order traversal result + for level in result: + printList(level) + ``` + + + + + + ```javascript + // TreeNode class represents + // a node in a binary tree + class TreeNode { + constructor(val = 0, left = null, right = null) { + this.val = val; + this.left = left; + this.right = right; + } + } + + class Solution { + // Function to perform level-order + // traversal of a binary tree + levelOrder(root) { + // Create an array to store levels + let ans = []; + if (!root) { + // If the tree is empty, + // return an empty array + return ans; + } + + // Create a queue to store + // nodes for level-order traversal + let q = []; + // Push the root node to the queue + q.push(root); + + while (q.length > 0) { + // Get the size of the current level + let size = q.length; + // Create an array to store + // nodes at the current level + let level = []; + + for (let i = 0; i < size; i++) { + // Get the front node in the queue + let node = q.shift(); + // Store the node value + // in the current level array + level.push(node.val); + + // Enqueue the child + // nodes if they exist + if (node.left !== null) { + q.push(node.left); + } + if (node.right !== null) { + q.push(node.right); + } + } + // Store the current level + // in the answer array + ans.push(level); + } + // Return the level-order + // traversal of the tree + return ans; + } + } + + // Function to print the + // elements of an array + function printArray(arr) { + // Iterate through the + // array and print each element + for (let num of arr) { + console.log(num + " "); + } + console.log("\n"); + } + + // Creating a sample binary tree + let root = new TreeNode(1); + root.left = new TreeNode(2); + root.right = new TreeNode(3); + root.left.left = new TreeNode(4); + root.left.right = new TreeNode(5); + + // Create an instance of the Solution class + let solution = new Solution(); + // Perform level-order traversal + let result = solution.levelOrder(root); + + console.log("Level Order Traversal of Tree: \n"); + + // Printing the level order traversal result + for (let level of result) { + printArray(level); + } + ``` + + + + +#### Complexity Analysis + +- **Time Complexity:** O(N) where N is the number of nodes in the binary tree. Each node of the binary tree is enqueued and dequeued exactly once, hence all nodes need to be processed and visited. Processing each node takes constant time operations which contributes to the overall linear time complexity. + +- **Space Complexity:** O(N) where N is the number of nodes in the binary tree. In the worst case, the queue has to hold all the nodes of the last level of the binary tree, the last level could at most hold N/2 nodes hence the space complexity of the queue is proportional to O(N). The resultant vector answer also stores the values of the nodes level by level and hence contains all the nodes of the tree contributing to O(N) space as well. + +--- + +## References + +- **LeetCode Problem:** [Symmetric Tree Problem](https://leetcode.com/problems/symmetric-tree/) +- **Solution Link:** [Symmetric Tree Solution on LeetCode](https://leetcode.com/problems/symmetric-tree/solutions/5016750/easy-recursion-solution-in-c-100-beats-full-expanation-with-example/) +- **Authors GeeksforGeeks Profile:** [Vipul lakum](https://leetcode.com/u/vipul_lakum_02/) From 3dd9af1b962ced9b3c9feede932a53a095db463e Mon Sep 17 00:00:00 2001 From: Vipul_Lakum Date: Tue, 4 Jun 2024 19:24:10 +0530 Subject: [PATCH 5/5] Remove duplicate from sorted list solution added --- ...0083-remove-duplicates-from-sorted-list.md | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 dsa-solutions/lc-solutions/0000-0099/0083-remove-duplicates-from-sorted-list.md diff --git a/dsa-solutions/lc-solutions/0000-0099/0083-remove-duplicates-from-sorted-list.md b/dsa-solutions/lc-solutions/0000-0099/0083-remove-duplicates-from-sorted-list.md new file mode 100644 index 000000000..ce0022bd6 --- /dev/null +++ b/dsa-solutions/lc-solutions/0000-0099/0083-remove-duplicates-from-sorted-list.md @@ -0,0 +1,121 @@ +--- +id: remove-duplicates-from-sorted-list +title: Remove Duplicates from Sorted List Solution +sidebar_label: 0083 Remove Duplicates from Sorted List +tags: + - Linked List + - Two Pointers + - LeetCode + - Python + - Java + - C++ +description: "This is a solution to the Remove Duplicates from Sorted List problem on LeetCode." +--- + +## Problem Description + +Given the head of a sorted linked list, delete all duplicates such that each element appears only once. Return the linked list sorted as well. + +### Examples + +**Example 1:** +``` +Input: head = [1,1,2] +Output: [1,2] +``` + +**Example 2:** + +``` +Input: head = [1,1,2,3,3] +Output: [1,2,3] +``` + +### Approach for Removing Duplicates from Sorted List + +**Intuition:** +The problem requires removing duplicates from a sorted singly-linked list. The approach involves iterating through the list and removing duplicates while maintaining the sorted order. + +**Approach:** +- Initialize a pointer `current` to the head of the linked list to traverse the list. +- Start a `while` loop that continues until `current` reaches the end of the list or `current.next` reaches null. +- Inside the loop, compare the value of the current node `current.val` with the value of the next node `current.next.val`. +- If the values are equal, it indicates a duplicate node. In this case, update the next pointer of the current node `current.next` to skip the next node (remove the duplicate). +- If the values are not equal, move the `current` pointer to the next node, continuing the traversal. +- Repeat the loop until the end of the list is reached, ensuring that all duplicates are removed while maintaining the sorted order of the remaining nodes. +- After the loop, return the modified linked list, which contains no duplicates. + + +### Code in Different Languages + +#### Java (code): + +```java +class Solution { + public ListNode deleteDuplicates(ListNode head) { + ListNode current = head; + + while (current != null && current.next != null) { + if (current.val == current.next.val) { + current.next = current.next.next; + } else { + current = current.next; + } + } + + return head; + } +} +``` + +#### Python (code) + +```python +class Solution: + def deleteDuplicates(self, head: ListNode) -> ListNode: + current = head + + while current and current.next: + if current.val == current.next.val: + current.next = current.next.next + else: + current = current.next + + return head +``` + +#### CPP (code) ; + +```cpp +class Solution { +public: + ListNode* deleteDuplicates(ListNode* head) { + ListNode* current = head; + + while (current && current->next) { + if (current->val == current->next->val) { + current->next = current->next->next; + } else { + current = current->next; + } + } + + return head; + } +}; +``` + +#### Complexity Analysis + +- **Time Complexity:** O(n) + + - The algorithm iterates through the linked list once, where n is the number of nodes in the list. Each node is examined once to identify and remove duplicates. + +- **Space Complexity:** O(1) + - The algorithm uses a constant amount of additional memory space for variables, regardless of the size of the input linked list, making its space complexity constant. + +## References + +- **LeetCode Problem**: [Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) +- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/balanced-binary-tree/solution/) +- **Authors GeeksforGeeks Profile:** [Vipul lakum](https://leetcode.com/u/vipul_lakum_02/) \ No newline at end of file