├── Blind 75 ├── 40. Reverse Bits.md ├── 41. Number of 1 Bits.md ├── 59. Missing Number.md ├── 50. Contains Duplicate.md ├── 56. Meeting Rooms.md ├── 69. Sum of Two Integers.md ├── 01. Two Sum.md ├── 67. Counting Bits.md ├── 38. Maximum Product Subarray.md ├── 72. Non-overlapping Intervals.md ├── 39. Find Minimum in Rotated Sorted Array.md ├── 20. Climbing Stairs.md ├── 51. Invert Binary Tree.md ├── 55. Valid Anagram.md ├── 07. Valid Parentheses.md ├── 44. Reverse Linked List.md ├── 36. Linked List Cycle.md ├── 16. Jump Game.md ├── 14. Maximum Subarray.md ├── 54. Product of Array Except Self.md ├── 53. Lowest Common Ancestor of a Binary Search Tree.md ├── 28. Maximum Depth of Binary Tree.md ├── 57. Meeting Rooms II.md ├── 64. Longest Increasing Subsequence.md ├── 19. Unique Paths.md ├── 52. Kth Smallest Element in a BST.md ├── 26. Same Tree.md ├── 04. Container With Most Water.md ├── 71. Longest Repeating Character Replacement.md ├── 05. 3Sum.md ├── 12. Rotate Image.md ├── 32. Valid Palindrome.md ├── 61. Encode and Decode Strings.md ├── 18. Insert Interval.md ├── 74. Palindromic Substrings.md ├── 30. Best Time to Buy and Sell Stock.md ├── 17. Merge Intervals.md ├── 75. Longest Common Subsequence.md ├── 42. House Robber.md ├── 24. Decode Ways.md ├── 02. Longest Substring Blind 75Without Repeating Characters.md ├── 68. Top K Frequent Elements.md ├── 03. Longest Palindromic Substring.md ├── 13. Group Anagrams.md ├── 62. Find Median from Data Stream.md ├── 25. Validate Binary Search Tree.md ├── 35. Word Break.md ├── 06. Remove Nth Node From End of List.md ├── 08. Merge Two Sorted Lists.md ├── 49. House Robber II.md ├── 15. Spiral Matrix.md ├── 37. Reorder List.md ├── 21. Set Matrix Zeroes.md ├── 11. Combination Sum.md ├── 65. Coin Change.md ├── 73. Subtree of Another Tree.md ├── 66. Number of Connected Components in an Undirected Graph.md ├── 58. Graph Valid Tree.md ├── 47. Design Add and Search Words Data Structure.md ├── 09. Merge k Sorted Lists.md ├── 45. Course Schedule.md ├── 34. Clone Graph.md ├── 23. Word Search.md ├── 31. Binary Tree Maximum Path Sum.md ├── 27. Binary Tree Level Order Traversal.md ├── 10. Search in Rotated Sorted Array.md ├── 48. Word Search II.md ├── 46. Implement Trie (Prefix Tree).md ├── 29. Construct Binary Tree from Preorder and Inorder Traversal.md ├── 70. Pacific Atlantic Water Flow.md ├── 63. Serialize and Deserialize Binary Tree.md ├── 60. Alien Dictionary.md ├── 33. Longest Consecutive Sequence.md ├── 22. Minimum Window Substring.md └── 43. Number of Islands.md └── README.md /Blind 75/40. Reverse Bits.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 190: [Reverse Bits](https://leetcode.com/problems/reverse-bits/) 2 | 3 | ## Problem Description 4 | 5 | Reverse bits of a given 32 bits unsigned integer. 6 | 7 | ## Solution Approach 8 | 9 | We iterate through each bit of the given integer and reverse its position. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | public class Solution { 15 | // you need treat n as an unsigned value 16 | public int reverseBits(int n) { 17 | int ans = 0; 18 | for (int i = 0; i < 32; i++) { 19 | if ((n & (1 << i)) != 0) 20 | ans = ans << 1 | 1; 21 | else 22 | ans = ans << 1; 23 | } 24 | return ans; 25 | } 26 | } 27 | ``` 28 | 29 | ## Complexity Analysis 30 | 31 | - **Time Complexity**: O(1). We iterate through 32 bits of the integer, which is constant. 32 | - **Space Complexity**: O(1). Constant space is used. 33 | 34 | ## Code Explanation 35 | 36 | - We initialize an integer `ans` to store the reversed bits. 37 | - We iterate through each bit of the given integer `n`. 38 | - If the bit is set (1), we set the corresponding bit in the answer `ans`. 39 | - Otherwise, we shift the answer `ans` to the left. 40 | - Finally, we return the reversed integer `ans`. 41 | -------------------------------------------------------------------------------- /Blind 75/41. Number of 1 Bits.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 191: [Number of 1 Bits](https://leetcode.com/problems/number-of-1-bits/) 2 | 3 | ## Problem Description 4 | 5 | Write a function that takes an unsigned integer and returns the number of '1' bits it has (also known as the Hamming weight). 6 | 7 | ## Solution Approach 8 | 9 | We iterate through each bit of the given integer and count the number of set bits. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | public class Solution { 15 | // you need to treat n as an unsigned value 16 | public int hammingWeight(int n) { 17 | int count=0; 18 | for(int i=0;i<32;i++) 19 | { 20 | count+=(n&1); 21 | n=n>>1; 22 | } 23 | return count; 24 | } 25 | } 26 | ``` 27 | 28 | ## Complexity Analysis 29 | 30 | - **Time Complexity**: O(1). We iterate through 32 bits of the integer, which is constant. 31 | - **Space Complexity**: O(1). Constant space is used. 32 | 33 | ## Code Explanation 34 | 35 | - We initialize an integer `count` to store the count of set bits (1s). 36 | - We iterate through each bit of the given integer `n`. 37 | - If the least significant bit is set (1), we increment the count. 38 | - We right shift the integer `n` by one bit. 39 | - Finally, we return the count of set bits. 40 | -------------------------------------------------------------------------------- /Blind 75/59. Missing Number.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 268: [Missing Number](https://leetcode.com/problems/missing-number/) 2 | 3 | ## Problem Description 4 | 5 | Given an array `nums` containing n distinct numbers in the range `[0, n]`, return the only number in the range that is missing from the array. 6 | 7 | 8 | ## Solution Approach 9 | 10 | To find the missing number, we can utilize the XOR operation. We iterate through the array and XOR each element with its index and the index range [0, n]. The missing number will be revealed through the XOR operation. 11 | 12 | ## Java Solution 13 | 14 | ```java 15 | class Solution { 16 | public int missingNumber(int[] nums) { 17 | int ans = 0; 18 | for (int i = 0; i < nums.length; i++) 19 | ans = ans ^ nums[i] ^ (i + 1); 20 | return ans; 21 | } 22 | } 23 | ``` 24 | 25 | ## Complexity Analysis 26 | 27 | - **Time Complexity**: O(n), where n is the length of the input array `nums`. We iterate through the array once. 28 | - **Space Complexity**: O(1), no extra space is used. 29 | 30 | ## Code Explanation 31 | 32 | - We initialize a variable `ans` to 0. 33 | - We iterate through the array `nums` and perform XOR (^) operation between `ans`, each element in `nums`, and the index plus 1. 34 | - After the iteration, `ans` will hold the missing number, which we return. 35 | -------------------------------------------------------------------------------- /Blind 75/50. Contains Duplicate.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 217: [Contains Duplicate](https://leetcode.com/problems/contains-duplicate/) 3 | 4 | ## Problem Description 5 | 6 | Given an integer array `nums`, return true if any value appears at least twice in the array, and return false if every element is distinct. 7 | 8 | ## Solution Approach 9 | 10 | We can solve this problem using a HashSet. We iterate through the array and add each element to the HashSet. If we encounter an element that is already present in the HashSet, it means the array contains a duplicate, and we return true. Otherwise, we return false. 11 | 12 | ## Java Solution 13 | 14 | ```java 15 | class Solution { 16 | public boolean containsDuplicate(int[] nums) { 17 | Set s = new HashSet(); 18 | int n = nums.length; 19 | for (int i = 0; i < n; i++) 20 | s.add(nums[i]); 21 | 22 | return s.size() != n; 23 | } 24 | } 25 | ``` 26 | 27 | ## Complexity Analysis 28 | 29 | - **Time Complexity**: O(N), where N is the number of elements in the array. 30 | - **Space Complexity**: O(N), where N is the number of elements in the array. 31 | 32 | ## Code Explanation 33 | 34 | - We use a HashSet to store unique elements from the array. 35 | - We iterate through the array and add each element to the HashSet. 36 | - If the size of the HashSet is not equal to the number of elements in the array, it means there are duplicate elements, and we return true. 37 | - Otherwise, we return false. 38 | -------------------------------------------------------------------------------- /Blind 75/56. Meeting Rooms.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 252: [Meeting Rooms](https://leetcode.com/problems/meeting-rooms/) 2 | 3 | ## Problem Description 4 | 5 | Given an array of meeting time intervals `intervals` where `intervals[i] = [starti, endi]`, determine if a person could attend all meetings. 6 | 7 | ## Solution Approach 8 | 9 | To solve this problem, we can sort the intervals based on the start time. Then, we iterate through the sorted intervals and check if there is any overlap between adjacent intervals. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | import java.util.Arrays; 15 | 16 | class Solution { 17 | public boolean canAttendMeetings(int[][] intervals) { 18 | Arrays.sort(intervals, (a, b) -> a[0] - b[0]); 19 | for (int i = 1; i < intervals.length; i++) { 20 | if (intervals[i][0] < intervals[i - 1][1]) { 21 | return false; 22 | } 23 | } 24 | return true; 25 | } 26 | } 27 | ``` 28 | 29 | ## Complexity Analysis 30 | 31 | - **Time Complexity**: O(N log N), where N is the number of intervals. We sort the intervals based on the start time. 32 | - **Space Complexity**: O(1), no extra space is used other than the input array. 33 | 34 | ## Code Explanation 35 | 36 | - We sort the intervals based on the start time using a custom comparator. 37 | - Then, we iterate through the sorted intervals and check if there is any overlap between adjacent intervals by comparing the start time of the current interval with the end time of the previous interval. 38 | -------------------------------------------------------------------------------- /Blind 75/69. Sum of Two Integers.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 371: [Sum of Two Integers](https://leetcode.com/problems/sum-of-two-integers/) 2 | 3 | ## Problem Description 4 | 5 | Calculate the sum of two integers `a` and `b`, but you are not allowed to use the operator + and -. 6 | 7 | ## Solution Approach 8 | 9 | We use bitwise manipulation to calculate the sum of two integers without using the `+` and `-` operators. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public int getSum(int a, int b) { 16 | while (b != 0) { 17 | int carry = a & b; 18 | a = a ^ b; 19 | b = carry << 1; 20 | } 21 | return a; 22 | } 23 | } 24 | ``` 25 | 26 | ## Complexity Analysis 27 | 28 | - **Time Complexity**: O(1). The time complexity is constant as the number of iterations in the while loop is limited by the number of bits in the input integers. 29 | - **Space Complexity**: O(1). The space complexity is constant as we are not using any extra space that grows with the input size. 30 | 31 | ## Code Explanation 32 | 33 | - We use bitwise operators to simulate addition without using the `+` and `-` operators. 34 | - Inside the while loop, we calculate the carry using the bitwise AND (`&`) operator and set `b` to the carry shifted one position to the left. 35 | - We update `a` by performing the bitwise XOR (`^`) operation between `a` and `b`. 36 | - We continue this process until `b` becomes zero, which indicates that there is no carry left. 37 | - Finally, we return the value of `a`, which represents the sum of the two integers. 38 | -------------------------------------------------------------------------------- /Blind 75/01. Two Sum.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 1: [Two Sum](https://leetcode.com/problems/two-sum/) 2 | 3 | # Problem Description 4 | Given an array of integers nums and an integer target, return the indices of the two numbers such that they add up to target. 5 | You may assume that each input would have exactly one solution, and you may not use the same element twice. You can return the answer in any order. 6 | 7 | ## Solution Approach 8 | - Create a HashMap to store elements and their indices. 9 | - Iterate through the array. 10 | - Check if `target - nums[i]` exists in the HashMap. 11 | - If found, return the indices. 12 | - If not found, add the current element along with its index to the HashMap. 13 | 14 | ## Java Solution Code 15 | 16 | ```java 17 | import java.util.HashMap; 18 | 19 | class Solution { 20 | public int[] twoSum(int[] nums, int target) { 21 | HashMap map = new HashMap<>(); 22 | int ans[] = new int[2]; 23 | 24 | for(int i=0;i> 1; 29 | } 30 | return count; 31 | } 32 | } 33 | ``` 34 | 35 | ## Complexity Analysis 36 | 37 | - **Time Complexity**: O(n * 32) = O(n). We iterate through each number from `0` to `n` and, for each number, perform up to 32 bit operations. 38 | - **Space Complexity**: O(n). We use an additional array of size `(n + 1)` to store the counts of set bits. 39 | 40 | ## Code Explanation 41 | 42 | - We iterate through numbers from `0` to `n`. 43 | - For each number, we count the number of set bits (1s) in its binary representation using the function `countSetBits`. 44 | - We store this count in the result array. 45 | -------------------------------------------------------------------------------- /Blind 75/38. Maximum Product Subarray.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 152: [Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/) 2 | 3 | ## Problem Description 4 | 5 | Given an integer array `nums`, find the contiguous subarray within an array (containing at least one number) which has the largest product. 6 | 7 | ## Solution Approach 8 | 9 | We use a dynamic programming approach to keep track of both the maximum and minimum product ending at each index. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | import java.util.*; 15 | 16 | class Solution { 17 | public int maxProduct(int[] nums) { 18 | int ans = nums[0]; 19 | int maxi = 1, mini = 1; 20 | 21 | for (int i = 0; i < nums.length; i++) { 22 | int temp = maxi; 23 | maxi = Math.max(Math.max(maxi * nums[i], mini * nums[i]), nums[i]); 24 | mini = Math.min(Math.min(temp * nums[i], mini * nums[i]), nums[i]); 25 | 26 | ans = Math.max(ans, maxi); 27 | } 28 | 29 | return ans; 30 | } 31 | } 32 | ``` 33 | 34 | ## Complexity Analysis 35 | 36 | - **Time Complexity**: O(N), where N is the length of the input array `nums`. We traverse the array once. 37 | - **Space Complexity**: O(1), constant space is used. 38 | 39 | ## Code Explanation 40 | 41 | - We initialize variables `maxi` and `mini` to keep track of the maximum and minimum product ending at each index. 42 | - We iterate through the array and update `maxi` and `mini` based on the current element and previous maximum and minimum products. 43 | - We update `ans` with the maximum product encountered so far and return it at the end. 44 | -------------------------------------------------------------------------------- /Blind 75/72. Non-overlapping Intervals.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 435: [Non-overlapping Intervals](https://leetcode.com/problems/non-overlapping-intervals/) 2 | 3 | ## Problem Description 4 | 5 | Given an array of intervals `intervals` where `intervals[i] = [starti, endi]`, return the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping. 6 | 7 | ## Solution Approach 8 | 9 | To solve this problem, we can sort the intervals based on their end times. Then, we iterate through the sorted intervals and count the number of intervals that overlap with the current one. We keep track of the previous end time and update it accordingly. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public int eraseOverlapIntervals(int[][] intervals) { 16 | Arrays.sort(intervals, (a, b) -> Integer.compare(a[1], b[1])); 17 | 18 | int count = 0, prevEnd = intervals[0][1]; 19 | for (int i = 1; i < intervals.length; i++) { 20 | if (intervals[i][0] < prevEnd) { 21 | count++; 22 | } else { 23 | prevEnd = intervals[i][1]; 24 | } 25 | } 26 | return count; 27 | } 28 | } 29 | ``` 30 | 31 | ## Complexity Analysis 32 | 33 | - **Time Complexity**: O(n log n) for sorting the intervals, where n is the number of intervals. 34 | - **Space Complexity**: O(1) since we use only a constant amount of space. 35 | 36 | ## Code Explanation 37 | 38 | - We sort the intervals based on their end times using Arrays.sort(). 39 | - We iterate through the sorted intervals and count the number of intervals that overlap with the current one. 40 | - We keep track of the previous end time and update it accordingly. 41 | -------------------------------------------------------------------------------- /Blind 75/39. Find Minimum in Rotated Sorted Array.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 153: [Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/) 2 | 3 | ## Problem Description 4 | 5 | Suppose an array of length n sorted in ascending order is rotated between 1 and n times. Given the sorted rotated array `nums`, return the minimum element of this array. 6 | 7 | ## Solution Approach 8 | 9 | We use binary search to find the minimum element in the rotated sorted array. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public int findMin(int[] nums) { 16 | int n = nums.length; 17 | if (n == 1 || nums[0] < nums[n - 1]) 18 | return nums[0]; 19 | if (nums[n - 1] < nums[n - 2]) 20 | return nums[n - 1]; 21 | 22 | int low = 1, high = n - 2; 23 | while (low <= high) { 24 | int mid = low + (high - low) / 2; 25 | 26 | if (nums[mid] < nums[mid - 1] && nums[mid] < nums[mid + 1]) { 27 | return nums[mid]; 28 | } else if (nums[mid] > nums[high]) 29 | low = mid + 1; 30 | else 31 | high = mid - 1; 32 | } 33 | return nums[low]; 34 | } 35 | } 36 | ``` 37 | 38 | ## Complexity Analysis 39 | 40 | - **Time Complexity**: O(log N), where N is the length of the input array `nums`. We perform binary search to find the minimum element. 41 | - **Space Complexity**: O(1), constant space is used. 42 | 43 | ## Code Explanation 44 | 45 | - We initialize variables `low` and `high` to perform binary search. 46 | - We iterate through the array using binary search to find the minimum element. 47 | - We return the minimum element found after binary search. 48 | -------------------------------------------------------------------------------- /Blind 75/20. Climbing Stairs.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 70: [Climbing Stairs](https://leetcode.com/problems/climbing-stairs/) 3 | 4 | ## Problem Description 5 | You are climbing a staircase. It takes `n` steps to reach the top. 6 | Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top? 7 | 8 | ## Solution Approach 9 | - We use dynamic programming to solve this problem. 10 | - We create an array `dp` to store the number of distinct ways to climb to each step. 11 | - We initialize the base cases for `dp[0]` and `dp[1]`, as there is only 1 way to climb for these steps. 12 | - We iterate from step 2 to `n` and calculate the number of distinct ways to reach each step using the formula: `dp[i] = dp[i-1] + dp[i-2]`. 13 | 14 | ## Java Solution Code 15 | 16 | ```java 17 | class Solution { 18 | public int climbStairs(int n) { 19 | int[] dp = new int[n + 1]; 20 | dp[0] = 1; 21 | dp[1] = 1; 22 | for (int i = 2; i <= n; i++) { 23 | dp[i] = dp[i - 1] + dp[i - 2]; 24 | } 25 | return dp[n]; 26 | } 27 | } 28 | ``` 29 | 30 | ## Complexity Analysis 31 | - **Time Complexity**: O(n), where n is the number of steps. 32 | - **Space Complexity**: O(n), for the dynamic programming array `dp`. 33 | 34 | ## Code Explanation 35 | 1. We create an array `dp` to store the number of distinct ways to climb to each step. 36 | 2. We initialize the base cases for `dp[0]` and `dp[1]` to 1, as there is only one way to climb for these steps. 37 | 3. We iterate from step 2 to `n` and calculate the number of distinct ways to reach each step using the formula: `dp[i] = dp[i-1] + dp[i-2]`. 38 | 4. Finally, we return `dp[n]`, which represents the number of distinct ways to climb to the top of the staircase with `n` steps. 39 | -------------------------------------------------------------------------------- /Blind 75/51. Invert Binary Tree.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 226: [Invert Binary Tree](https://leetcode.com/problems/invert-binary-tree/) 2 | 3 | ## Problem Description 4 | 5 | Given the root of a binary tree, invert the tree, and return its root. 6 | 7 | ## Solution Approach 8 | 9 | We can solve this problem recursively. We swap the left and right children of each node recursively until we reach the leaf nodes. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | /** 15 | * Definition for a binary tree node. 16 | * public class TreeNode { 17 | * int val; 18 | * TreeNode left; 19 | * TreeNode right; 20 | * TreeNode() {} 21 | * TreeNode(int val) { this.val = val; } 22 | * TreeNode(int val, TreeNode left, TreeNode right) { 23 | * this.val = val; 24 | * this.left = left; 25 | * this.right = right; 26 | * } 27 | * } 28 | */ 29 | class Solution { 30 | public TreeNode invertTree(TreeNode root) { 31 | if (root == null) 32 | return root; 33 | TreeNode temp = root.left; 34 | root.left = root.right; 35 | root.right = temp; 36 | if (root.left != null) 37 | invertTree(root.left); 38 | if (root.right != null) 39 | invertTree(root.right); 40 | 41 | return root; 42 | } 43 | } 44 | ``` 45 | 46 | ## Complexity Analysis 47 | 48 | - **Time Complexity**: O(N), where N is the number of nodes in the binary tree. 49 | - **Space Complexity**: O(H), where H is the height of the binary tree. 50 | 51 | ## Code Explanation 52 | 53 | - We start with the root node. 54 | - If the root is null, we return null. 55 | - Otherwise, we swap the left and right children of the root node. 56 | - Then, we recursively call the `invertTree` function for the left and right subtrees. 57 | - Finally, we return the root node. 58 | -------------------------------------------------------------------------------- /Blind 75/55. Valid Anagram.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 242: [Valid Anagram](https://leetcode.com/problems/valid-anagram/) 2 | 3 | ## Problem Description 4 | 5 | Given two strings s and t, return true if t is an anagram of s, and false otherwise. 6 | 7 | ## Solution Approach 8 | 9 | To solve this problem, we can use a hashmap to store the frequency of characters in the first string. Then, we iterate through the second string and decrement the frequency of each character encountered. If the frequency of characters in both strings matches, then the strings are anagrams. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public boolean isAnagram(String s, String t) { 16 | Map mp = new HashMap<>(); 17 | int n = s.length(), m = t.length(); 18 | if (n != m) 19 | return false; 20 | for (int i = 0; i < n; i++) { 21 | char ch = s.charAt(i); 22 | mp.put(ch, mp.getOrDefault(ch, 0) + 1); 23 | if (mp.get(ch) == 0) 24 | mp.remove(ch); 25 | 26 | char ch2 = t.charAt(i); 27 | mp.put(ch2, mp.getOrDefault(ch2, 0) - 1); 28 | if (mp.get(ch2) == 0) 29 | mp.remove(ch2); 30 | } 31 | return mp.isEmpty(); 32 | } 33 | } 34 | ``` 35 | 36 | ## Complexity Analysis 37 | 38 | - **Time Complexity**: O(N), where N is the length of the input strings s and t. We iterate through both strings once. 39 | - **Space Complexity**: O(1) if we don't consider the space required for the hashmap, otherwise O(N) for the hashmap to store character frequencies. 40 | 41 | ## Code Explanation 42 | 43 | - We use a hashmap to store the frequency of characters in the first string. 44 | - Then, we iterate through the second string and decrement the frequency of each character encountered. 45 | - If the frequency of characters in both strings matches, then the strings are anagrams. 46 | -------------------------------------------------------------------------------- /Blind 75/07. Valid Parentheses.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 20: [Valid Parentheses](https://leetcode.com/problems/valid-parentheses/) 2 | 3 | ## Problem Description 4 | Given a string `s` containing just the characters `'(', ')', '{', '}', '['` and `']'`, determine if the input string is valid. 5 | 6 | An input string is valid if: 7 | 1. Open brackets must be closed by the same type of brackets. 8 | 2. Open brackets must be closed in the correct order. 9 | 10 | ## Java Solution Code 11 | 12 | ```java 13 | import java.util.Stack; 14 | 15 | class Solution { 16 | public boolean isValid(String s) { 17 | Stack stack = new Stack<>(); 18 | int n = s.length(); 19 | 20 | for (int i = 0; i < n; i++) { 21 | char ch = s.charAt(i); 22 | if (ch == '(' || ch == '[' || ch == '{') { 23 | stack.push(ch); 24 | } else { 25 | if (stack.isEmpty()) { 26 | return false; 27 | } 28 | char top = stack.pop(); 29 | if ((ch == ')' && top != '(') || (ch == ']' && top != '[') || (ch == '}' && top != '{')) { 30 | return false; 31 | } 32 | } 33 | } 34 | return stack.isEmpty(); 35 | } 36 | } 37 | ``` 38 | 39 | ## Complexity Analysis 40 | - **Time Complexity**: O(n), where n is the length of the input string `s`. 41 | - **Space Complexity**: O(n), where n is the length of the input string `s`, as we use a stack to store the opening parentheses. 42 | 43 | ## Code Explanation 44 | - We iterate through the characters of the input string `s`. 45 | - We push opening parentheses onto the stack. 46 | - When we encounter a closing parentheses, we check if the stack is empty or if the top element of the stack matches the corresponding opening parentheses. 47 | - At the end, we return true if the stack is empty, indicating all parentheses are matched. 48 | -------------------------------------------------------------------------------- /Blind 75/44. Reverse Linked List.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem: [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/) 2 | 3 | ## Problem Description 4 | 5 | Given the head of a singly linked list, reverse the list, and return its head. 6 | 7 | ## Solution Approach 8 | 9 | To reverse a linked list, we iterate through the list while maintaining references to the previous, current, and next nodes. We update the next pointer of the current node to point to its previous node. Finally, we update the previous and current pointers for the next iteration. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | /** 15 | * Definition for singly-linked list. 16 | * public class ListNode { 17 | * int val; 18 | * ListNode next; 19 | * ListNode() {} 20 | * ListNode(int val) { this.val = val; } 21 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 22 | * } 23 | */ 24 | class Solution { 25 | public ListNode reverseList(ListNode head) { 26 | ListNode prevNode = null, curNode = head, nextNode = null; 27 | 28 | while (curNode != null) { 29 | nextNode = curNode.next; 30 | curNode.next = prevNode; 31 | prevNode = curNode; 32 | curNode = nextNode; 33 | } 34 | return prevNode; 35 | } 36 | } 37 | ``` 38 | 39 | ## Complexity Analysis 40 | 41 | - **Time Complexity**: O(n), where n is the number of nodes in the linked list. We traverse the list once. 42 | - **Space Complexity**: O(1), constant space is used. 43 | 44 | ## Code Explanation 45 | 46 | 1. We initialize three pointers: `prevNode`, `curNode`, and `nextNode`. 47 | 2. We iterate through the linked list, updating the `next` pointer of each node to point to its previous node. 48 | 3. We update the `prevNode`, `curNode`, and `nextNode` pointers for the next iteration. 49 | 4. Finally, we return the `prevNode`, which now points to the head of the reversed linked list. 50 | -------------------------------------------------------------------------------- /Blind 75/36. Linked List Cycle.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 141: [Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/) 2 | 3 | ## Problem Description 4 | 5 | Given head, the head of a linked list, determine if the linked list has a cycle in it. 6 | 7 | ## Solution Approach 8 | 9 | We use Floyd's Tortoise and Hare algorithm to detect cycles in the linked list. We have two pointers, `slow` and `fast`, initially pointing to the head of the linked list. The `slow` pointer moves one step at a time while the `fast` pointer moves two steps at a time. If there is a cycle, eventually, the `fast` pointer will meet the `slow` pointer. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | /** 15 | * Definition for singly-linked list. 16 | * class ListNode { 17 | * int val; 18 | * ListNode next; 19 | * ListNode(int x) { 20 | * val = x; 21 | * next = null; 22 | * } 23 | * } 24 | */ 25 | public class Solution { 26 | public boolean hasCycle(ListNode head) { 27 | ListNode fast = head, slow = head; 28 | 29 | while (fast != null && fast.next != null) { 30 | slow = slow.next; 31 | fast = fast.next.next; 32 | if (slow == fast) 33 | return true; 34 | } 35 | return false; 36 | } 37 | } 38 | ``` 39 | 40 | ## Complexity Analysis 41 | 42 | - **Time Complexity**: \(O(n)\), where \(n\) is the number of nodes in the linked list. We iterate through the linked list once. 43 | - **Space Complexity**: \(O(1)\), constant space is used. 44 | 45 | ## Code Explanation 46 | 47 | 1. We define a function `hasCycle` that checks if the linked list has a cycle. 48 | 2. We use two pointers, `slow` and `fast`, initially pointing to the head of the linked list. 49 | 3. In each iteration, `slow` moves one step forward, while `fast` moves two steps forward. 50 | 4. If there is a cycle, eventually, the `fast` pointer will meet the `slow` pointer, and we return true. 51 | 5. If there is no cycle, the `fast` pointer will reach the end of the linked list, and we return false. 52 | -------------------------------------------------------------------------------- /Blind 75/16. Jump Game.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 55: [Jump Game](https://leetcode.com/problems/jump-game/) 3 | 4 | ## Problem Description 5 | Given an array of non-negative integers `nums`, you are initially positioned at the first index of the array. 6 | Each element in the array represents your maximum jump length at that position. Determine if you can reach the last index. 7 | 8 | ## Solution Approach 9 | - We traverse the array and maintain an auxiliary array `arr[]` to track the farthest reachable index at each position. 10 | - We iterate through the array and update `arr[i]` with the farthest index we can reach from index `i`. 11 | - If at any point, we cannot reach index `i` itself (meaning `arr[i-1] < i`), then we cannot proceed further, and we return `false`. 12 | - If we can reach the last index (`arr[n-1] >= n-1`), then we return `true`. 13 | 14 | ## Java Solution Code 15 | 16 | ```java 17 | class Solution { 18 | public boolean canJump(int[] nums) { 19 | int n = nums.length; 20 | if (n == 1) 21 | return true; 22 | 23 | int[] arr = new int[n]; 24 | arr[0] = nums[0]; 25 | 26 | for (int i = 1; i < n; i++) { 27 | if (arr[i - 1] >= i) 28 | arr[i] = Math.max(arr[i - 1], nums[i] + i); 29 | else 30 | return false; 31 | } 32 | return true; 33 | } 34 | } 35 | ``` 36 | 37 | ## Complexity Analysis 38 | - **Time Complexity**: O(n), where n is the length of the input array `nums`. 39 | - **Space Complexity**: O(n), where n is the length of the input array `nums`. 40 | 41 | ## Code Explanation 42 | 1. We initialize an array `arr[]` to track the farthest reachable index at each position. 43 | 2. We iterate through the array `nums` and update `arr[i]` with the farthest index we can reach from index `i`. 44 | 3. If at any point, we cannot reach index `i` itself (meaning `arr[i-1] < i`), then we cannot proceed further, and we return `false`. 45 | 4. If we can reach the last index (`arr[n-1] >= n-1`), then we return `true`. 46 | -------------------------------------------------------------------------------- /Blind 75/14. Maximum Subarray.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 53: [Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) 2 | 3 | ## Problem Description 4 | Given an integer array `nums`, find the contiguous subarray (containing at least one number) that has the largest sum and return its sum. 5 | 6 | A subarray is a contiguous part of an array. 7 | 8 | ## Solution Approach 9 | - We use Kadane's algorithm to find the maximum subarray sum. 10 | - We maintain two variables: `sum` to keep track of the current subarray sum and `largestSum` to store the maximum subarray sum seen so far. 11 | - We iterate through the array and update the `sum` by adding the current element if it increases the sum, or start a new subarray if it's greater than the sum. 12 | - We update `largestSum` with the maximum value of `largestSum` and `sum` in each iteration. 13 | 14 | ## Java Solution Code 15 | 16 | ```java 17 | class Solution { 18 | public int maxSubArray(int[] nums) { 19 | int largestSum = nums[0]; 20 | int sum = nums[0]; 21 | 22 | for (int i = 1; i < nums.length; i++) { 23 | if (nums[i] >= (sum + nums[i])) { 24 | sum = nums[i]; 25 | } else { 26 | sum += nums[i]; 27 | } 28 | largestSum = Math.max(largestSum, sum); 29 | } 30 | return largestSum; 31 | } 32 | } 33 | ``` 34 | 35 | ## Complexity Analysis 36 | - **Time Complexity**: O(n), where n is the length of the `nums` array. 37 | - We iterate through the array once. 38 | - **Space Complexity**: O(1), as we use only constant extra space. 39 | 40 | ## Code Explanation 41 | 1. We initialize two variables: `largestSum` and `sum` to the first element of the array `nums`. 42 | 2. We iterate through the array starting from the second element. 43 | 3. For each element `nums[i]`, we check if adding it to the current `sum` increases the sum or if it's better to start a new subarray. 44 | 4. We update the `sum` and `largestSum` accordingly in each iteration. 45 | 5. Finally, we return the `largestSum` as the result. 46 | -------------------------------------------------------------------------------- /Blind 75/54. Product of Array Except Self.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 238: [Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/) 2 | 3 | 4 | ## Problem Description 5 | 6 | Given an array `nums` of n integers where n > 1, return an array `output` such that `output[i]` is equal to the product of all the elements of `nums` except `nums[i]`. 7 | 8 | ## Solution Approach 9 | 10 | We can solve this problem by creating two arrays. First, we traverse the array from left to right and compute the product of all elements to the left of each element. Then, we traverse the array from right to left and compute the product of all elements to the right of each element. Finally, we multiply the corresponding elements from both arrays to get the desired result. 11 | 12 | ## Java Solution 13 | 14 | ```java 15 | class Solution { 16 | public int[] productExceptSelf(int[] nums) { 17 | int n = nums.length; 18 | int[] ans = new int[n]; 19 | 20 | ans[0] = nums[0]; 21 | for (int i = 1; i < n; i++) { 22 | ans[i] = nums[i] * ans[i - 1]; 23 | } 24 | 25 | int product = nums[n - 1]; 26 | ans[n - 1] = ans[n - 2]; 27 | for (int i = n - 2; i >= 1; i--) { 28 | ans[i] = product * ans[i - 1]; 29 | product *= nums[i]; 30 | } 31 | ans[0] = product; 32 | 33 | return ans; 34 | } 35 | } 36 | ``` 37 | 38 | ## Complexity Analysis 39 | 40 | - **Time Complexity**: O(N), where N is the length of the input array `nums`. We traverse the array twice. 41 | - **Space Complexity**: O(1) if we don't consider the space required for the output array, otherwise O(N) for the output array. 42 | 43 | ## Code Explanation 44 | 45 | - We traverse the array from left to right and compute the product of all elements to the left of each element. 46 | - Then, we traverse the array from right to left and compute the product of all elements to the right of each element. 47 | - Finally, we multiply the corresponding elements from both arrays to get the desired result. 48 | -------------------------------------------------------------------------------- /Blind 75/53. Lowest Common Ancestor of a Binary Search Tree.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 235: [Lowest Common Ancestor of a Binary Search Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/) 2 | 3 | ## Problem Description 4 | 5 | Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. 6 | 7 | ## Solution Approach 8 | 9 | To find the lowest common ancestor (LCA) of two nodes in a BST, we start from the root node and traverse down the tree. At each step, we compare the values of the current node with the values of the two given nodes, `p` and `q`. Based on the values, we traverse left or right until we find the LCA. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | /** 15 | * Definition for a binary tree node. 16 | * public class TreeNode { 17 | * int val; 18 | * TreeNode left; 19 | * TreeNode right; 20 | * TreeNode(int x) { val = x; } 21 | * } 22 | */ 23 | 24 | class Solution { 25 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 26 | if(root == null) 27 | return null; 28 | if(root.val > p.val && root.val > q.val) 29 | return lowestCommonAncestor(root.left, p, q); 30 | if(root.val < p.val && root.val < q.val) 31 | return lowestCommonAncestor(root.right, p, q); 32 | return root; 33 | } 34 | } 35 | ``` 36 | 37 | ## Complexity Analysis 38 | 39 | - **Time Complexity**: O(H), where H is the height of the binary search tree. In the worst case, we traverse from the root node to the deepest leaf node. 40 | - **Space Complexity**: O(1) if the recursive call stack is not considered, otherwise O(H) for the recursive call stack. 41 | 42 | ## Code Explanation 43 | 44 | - We start from the root node and traverse down the tree. 45 | - At each step, we compare the values of the current node with the values of the two given nodes, `p` and `q`. 46 | - Based on the values, we traverse left or right until we find the lowest common ancestor (LCA) of `p` and `q`. 47 | - We return the LCA node found. 48 | -------------------------------------------------------------------------------- /Blind 75/28. Maximum Depth of Binary Tree.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 104: [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) 2 | 3 | ## Problem Description 4 | Given the root of a binary tree, return its maximum depth. A binary tree's maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 5 | 6 | ## Solution Approach 7 | - We recursively calculate the maximum depth of the left and right subtrees. 8 | - The maximum depth of the binary tree is the maximum of the depths of the left and right subtrees plus 1. 9 | 10 | ## Java Solution Code 11 | 12 | ```java 13 | /** 14 | * Definition for a binary tree node. 15 | * public class TreeNode { 16 | * int val; 17 | * TreeNode left; 18 | * TreeNode right; 19 | * TreeNode() {} 20 | * TreeNode(int val) { this.val = val; } 21 | * TreeNode(int val, TreeNode left, TreeNode right) { 22 | * this.val = val; 23 | * this.left = left; 24 | * this.right = right; 25 | * } 26 | * } 27 | */ 28 | class Solution { 29 | public int maxDepth(TreeNode root) { 30 | if(root == null) 31 | return 0; 32 | return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); 33 | } 34 | } 35 | ``` 36 | 37 | ## Complexity Analysis 38 | - **Time Complexity**: O(N), where N is the number of nodes in the binary tree. We visit each node once. 39 | - **Space Complexity**: O(H), where H is the height of the binary tree, representing the recursion stack space. 40 | 41 | ## Code Explanation 42 | 1. The `maxDepth` function takes the root of the binary tree as input and returns its maximum depth. 43 | 2. If the root is null, we return 0, indicating that the tree has no depth. 44 | 3. Otherwise, we recursively calculate the maximum depth of the left and right subtrees using the `maxDepth` function. 45 | 4. We take the maximum of the depths of the left and right subtrees and add 1 to it, representing the depth of the current node. 46 | 5. Finally, we return the maximum depth of the binary tree. 47 | -------------------------------------------------------------------------------- /Blind 75/57. Meeting Rooms II.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 253: [Meeting Rooms II](https://leetcode.com/problems/meeting-rooms-ii/) 2 | 3 | ## Problem Description 4 | 5 | Given an array of meeting time intervals `intervals` where `intervals[i] = [starti, endi]`, return the minimum number of conference rooms required. 6 | 7 | ## Solution Approach 8 | 9 | To solve this problem, we can use a priority queue to keep track of the ending times of ongoing meetings. We sort the intervals based on their start times and iterate through them. If the start time of the current interval is greater than or equal to the end time of the meeting with the earliest end time in the priority queue, we update that meeting with the current interval's end time. Otherwise, we add the current interval's end time to the priority queue, indicating the need for a new meeting room. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | import java.util.Arrays; 15 | import java.util.PriorityQueue; 16 | 17 | class Solution { 18 | public int minMeetingRooms(int[][] intervals) { 19 | Arrays.sort(intervals, (a, b) -> a[0] - b[0]); 20 | PriorityQueue pq = new PriorityQueue<>(); 21 | pq.offer(intervals[0][1]); 22 | for (int i = 1; i < intervals.length; i++) { 23 | if (intervals[i][0] >= pq.peek()) { 24 | pq.poll(); 25 | } 26 | pq.offer(intervals[i][1]); 27 | } 28 | return pq.size(); 29 | } 30 | } 31 | ``` 32 | 33 | ## Complexity Analysis 34 | 35 | - **Time Complexity**: O(N log N), where N is the number of intervals. We sort the intervals based on their start times. 36 | - **Space Complexity**: O(N), where N is the number of intervals. We use a priority queue to keep track of the ending times of ongoing meetings. 37 | 38 | ## Code Explanation 39 | 40 | - We sort the intervals based on their start times using a custom comparator. 41 | - We use a priority queue to keep track of the ending times of ongoing meetings. 42 | - We iterate through the sorted intervals and update the priority queue accordingly to determine the minimum number of conference rooms required. 43 | -------------------------------------------------------------------------------- /Blind 75/64. Longest Increasing Subsequence.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 300: [Length of Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/) 3 | 4 | ## Problem Description 5 | 6 | Given an unsorted array of integers, find the length of the longest increasing subsequence. 7 | 8 | ## Solution Approach 9 | 10 | We can solve this problem using dynamic programming. We initialize an array `dp` of the same length as the input array, where `dp[i]` represents the length of the longest increasing subsequence ending at index `i`. We then iterate through the array and update `dp[i]` based on the maximum length of increasing subsequences ending at indices before `i`. 11 | 12 | ## Java Solution 13 | 14 | ```java 15 | import java.util.Arrays; 16 | 17 | class Solution { 18 | public int lengthOfLIS(int[] nums) { 19 | int n = nums.length; 20 | int[] dp = new int[n]; 21 | Arrays.fill(dp, 1); 22 | 23 | int maxLength = 1; 24 | for (int i = 1; i < n; i++) { 25 | for (int j = 0; j < i; j++) { 26 | if (nums[i] > nums[j]) { 27 | dp[i] = Math.max(dp[i], 1 + dp[j]); 28 | } 29 | } 30 | maxLength = Math.max(maxLength, dp[i]); 31 | } 32 | return maxLength; 33 | } 34 | } 35 | ``` 36 | 37 | ## Complexity Analysis 38 | 39 | - **Time Complexity**: O(n^2), where n is the length of the input array. We have two nested loops to compute the longest increasing subsequence length for each element. 40 | - **Space Complexity**: O(n), where n is the length of the input array. We use an additional array `dp` of the same length as the input array. 41 | 42 | ## Code Explanation 43 | 44 | - We initialize an array `dp` to store the length of the longest increasing subsequence. 45 | - We fill the `dp` array with 1 initially, indicating the minimum length of increasing subsequence at each index. 46 | - We iterate through the array and update `dp[i]` based on the maximum length of increasing subsequences ending at indices before `i`. 47 | - We return the maximum value in the `dp` array as the result. 48 | -------------------------------------------------------------------------------- /Blind 75/19. Unique Paths.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 62: [Unique Paths](https://leetcode.com/problems/unique-paths/) 2 | 3 | ## Problem Description 4 | A robot is located at the top-left corner of a m x n grid. The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid. How many possible unique paths are there? 5 | 6 | ## Solution Approach 7 | - We use dynamic programming to solve this problem. 8 | - We create a 2D array `dp` to store the number of unique paths for each cell. 9 | - We iterate through each cell in the grid and calculate the number of unique paths based on the number of paths from the cells above and to the left. 10 | 11 | ## Java Solution Code 12 | 13 | ```java 14 | class Solution { 15 | public int uniquePaths(int m, int n) { 16 | int[][] dp = new int[m][n]; 17 | 18 | // Fill the first row and first column with 1 19 | for (int i = 0; i < m; i++) { 20 | dp[i][0] = 1; 21 | } 22 | for (int j = 0; j < n; j++) { 23 | dp[0][j] = 1; 24 | } 25 | 26 | // Calculate unique paths for each cell 27 | for (int i = 1; i < m; i++) { 28 | for (int j = 1; j < n; j++) { 29 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 30 | } 31 | } 32 | 33 | // Return the number of unique paths for the bottom-right cell 34 | return dp[m - 1][n - 1]; 35 | } 36 | } 37 | ``` 38 | 39 | ## Complexity Analysis 40 | - **Time Complexity**: O(m * n), where m is the number of rows and n is the number of columns. 41 | - **Space Complexity**: O(m * n), for the 2D array `dp`. 42 | 43 | ## Code Explanation 44 | 1. We create a 2D array `dp` to store the number of unique paths for each cell. 45 | 2. We fill the first row and first column with 1, as there is only one way to reach any cell in the first row or column. 46 | 3. We iterate through each cell in the grid (except the first row and first column) and calculate the number of unique paths based on the number of paths from the cells above and to the left. 47 | 4. Finally, we return the number of unique paths for the bottom-right cell. 48 | -------------------------------------------------------------------------------- /Blind 75/52. Kth Smallest Element in a BST.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 230: [Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/) 2 | 3 | ## Problem Description 4 | 5 | Given the root of a binary search tree (BST), return the kth smallest element in it. 6 | 7 | ## Solution Approach 8 | 9 | We perform an inorder traversal of the BST and keep track of the count of visited nodes. When the count reaches k, we have found the kth smallest element. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | /** 15 | * Definition for a binary tree node. 16 | * public class TreeNode { 17 | * int val; 18 | * TreeNode left; 19 | * TreeNode right; 20 | * TreeNode() {} 21 | * TreeNode(int val) { this.val = val; } 22 | * TreeNode(int val, TreeNode left, TreeNode right) { 23 | * this.val = val; 24 | * this.left = left; 25 | * this.right = right; 26 | * } 27 | * } 28 | */ 29 | class Solution { 30 | int kthElement = -1; 31 | int count = 0; 32 | 33 | public int kthSmallest(TreeNode root, int k) { 34 | inOrder(root, k); 35 | return kthElement; 36 | } 37 | 38 | void inOrder(TreeNode root, int k) { 39 | if (root == null) 40 | return; 41 | 42 | inOrder(root.left, k); 43 | count++; 44 | if (count == k) { 45 | kthElement = root.val; 46 | return; 47 | } 48 | inOrder(root.right, k); 49 | } 50 | } 51 | ``` 52 | 53 | ## Complexity Analysis 54 | 55 | - **Time Complexity**: O(N), where N is the number of nodes in the binary search tree. In the worst case, we visit all nodes to find the kth smallest element. 56 | - **Space Complexity**: O(H), where H is the height of the binary search tree. The space complexity is determined by the function call stack during the recursive inorder traversal. 57 | 58 | ## Code Explanation 59 | 60 | - We perform an inorder traversal of the binary search tree. 61 | - During traversal, we keep track of the count of visited nodes. 62 | - When the count reaches k, we have found the kth smallest element. 63 | - We return the value of the kth smallest element. 64 | -------------------------------------------------------------------------------- /Blind 75/26. Same Tree.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 100: [Same Tree](https://leetcode.com/problems/same-tree/) 2 | 3 | ## Problem Description 4 | Given the roots of two binary trees p and q, determine if they are the same. 5 | 6 | Two binary trees are considered the same if they are structurally identical and the nodes have the same value. 7 | 8 | ## Solution Approach 9 | - We use a recursive approach to traverse both trees simultaneously. 10 | - At each node, we compare their values and recursively check their left and right subtrees. 11 | 12 | ## Java Solution Code 13 | 14 | ```java 15 | /** 16 | * Definition for a binary tree node. 17 | * public class TreeNode { 18 | * int val; 19 | * TreeNode left; 20 | * TreeNode right; 21 | * TreeNode() {} 22 | * TreeNode(int val) { this.val = val; } 23 | * TreeNode(int val, TreeNode left, TreeNode right) { 24 | * this.val = val; 25 | * this.left = left; 26 | * this.right = right; 27 | * } 28 | * } 29 | */ 30 | class Solution { 31 | public boolean isSameTree(TreeNode p, TreeNode q) { 32 | if (p == null && q == null) 33 | return true; 34 | if (p == null || q == null) 35 | return false; 36 | 37 | return p.val == q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 38 | } 39 | } 40 | ``` 41 | 42 | ## Complexity Analysis 43 | - **Time Complexity**: O(N), where N is the number of nodes in the binary trees p and q. We visit each node once. 44 | - **Space Complexity**: O(N), for the recursive call stack, where N is the height of the binary trees in the worst case. 45 | 46 | ## Code Explanation 47 | 1. We use a recursive helper function `isSameTree` to compare the nodes of both trees. 48 | 2. If both trees are empty (null), they are considered the same. 49 | 3. If one tree is empty and the other is not, they are not the same. 50 | 4. Otherwise, we compare the values of the current nodes and recursively check their left and right subtrees. 51 | 5. If the values match and both subtrees are the same, we return `true`, indicating that the trees are the same. 52 | 6. We repeat this process for each node in both trees, starting from the root. 53 | -------------------------------------------------------------------------------- /Blind 75/04. Container With Most Water.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 11: [Container With Most Water](https://leetcode.com/problems/container-with-most-water/) 2 | 3 | ## Problem Description 4 | Given `n` non-negative integers `height[i]` where each represents a point at coordinate `(i, height[i])`, `n` vertical lines are drawn such that the two endpoints of the line `i` are at `(i, height[i])` and `(i, 0)`. Find two lines, which, together with the x-axis forms a container, such that the container contains the most water. 5 | 6 | **Notice**: You may not slant the container. 7 | 8 | ## Solution Approach 9 | - We use a two-pointer approach to find the maximum area between two lines. 10 | - Initialize two pointers, `left` and `right`, at the beginning and end of the array respectively. 11 | - Calculate the area between the lines using the formula `min(height[left], height[right]) * (right - left)`. 12 | - Update the maximum area if the calculated area is greater than the current maximum. 13 | - Move the pointer with the smaller height inward, as moving the pointer with the larger height cannot increase the area. 14 | 15 | ## Java Solution Code 16 | 17 | ```java 18 | class Solution { 19 | public int maxArea(int[] height) { 20 | int left = 0, right = height.length - 1; 21 | int area = 0; 22 | 23 | while (left < right) { 24 | int length = right - left; 25 | int width = Math.min(height[left], height[right]); 26 | area = Math.max(area, length * width); 27 | 28 | if (height[left] < height[right]) 29 | left++; 30 | else 31 | right--; 32 | } 33 | 34 | return area; 35 | } 36 | } 37 | ``` 38 | 39 | ## Complexity Analysis 40 | - **Time Complexity**: O(n), where n is the number of elements in the height array. 41 | - **Space Complexity**: O(1), as we use a constant amount of space. 42 | 43 | ## Code Explanation 44 | - Initialize two pointers, `left` and `right`, at the beginning and end of the array. 45 | - Move the pointers towards each other to find the maximum area between two lines. 46 | - Calculate the area using the formula and update the maximum area accordingly. 47 | - Continue this process until the two pointers meet. 48 | -------------------------------------------------------------------------------- /Blind 75/71. Longest Repeating Character Replacement.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 424: [Longest Repeating Character Replacement](Problem_Link) 3 | 4 | ## Problem Description 5 | 6 | Given a string `s` that consists of only uppercase English letters, you can perform at most `k` operations on that string. 7 | 8 | In one operation, you can choose any character of the string and change it to any other uppercase English character. 9 | 10 | Find the length of the longest substring containing all repeating letters you can get after performing the above operations. 11 | 12 | ## Solution Approach 13 | 14 | We use a sliding window approach to traverse the string while maintaining a hashmap to count the occurrences of each character. We also keep track of the maximum count of a character within the current window. 15 | 16 | ## Java Solution 17 | 18 | ```java 19 | class Solution { 20 | public int characterReplacement(String s, int k) { 21 | int i = 0, j = 0, maxLength = 0; 22 | HashMap mp = new HashMap<>(); 23 | 24 | int maxCount = 0; 25 | while (j < s.length()) { 26 | char ch = s.charAt(j); 27 | mp.put(ch, mp.getOrDefault(ch, 0) + 1); 28 | 29 | maxCount = Math.max(maxCount, mp.get(ch)); 30 | if (j - i + 1 - maxCount > k) { 31 | mp.put(s.charAt(i), mp.get(s.charAt(i)) - 1); 32 | i++; 33 | } 34 | maxLength = Math.max(maxLength, j - i + 1); 35 | j++; 36 | } 37 | 38 | return maxLength; 39 | } 40 | } 41 | ``` 42 | 43 | ## Complexity Analysis 44 | 45 | - **Time Complexity**: O(n), where n is the length of the string `s`. We traverse the string once using the sliding window approach. 46 | - **Space Complexity**: O(26) = O(1). The hashmap can contain at most 26 characters. 47 | 48 | ## Code Explanation 49 | 50 | - We maintain a sliding window `[i, j]` and a hashmap `mp` to count the occurrences of characters. 51 | - We update the maximum count of a character within the current window. 52 | - If the length of the window minus the maximum count exceeds `k`, we shrink the window from the left. 53 | - We update the maximum length of the substring containing all repeating letters. 54 | -------------------------------------------------------------------------------- /Blind 75/05. 3Sum.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 15: [3Sum](https://leetcode.com/problems/3sum/) 2 | 3 | ## Problem Description 4 | Given an integer array `nums`, return all the unique triplets `[nums[i], nums[j], nums[k]]` such that `i != j`, `i != k`, and `j != k`, and `nums[i] + nums[j] + nums[k] == 0`. Notice that the solution set must not contain duplicate triplets. 5 | 6 | 7 | ## Solution Approach 8 | - We sort the array `nums` to simplify the process of finding triplets. 9 | - We iterate through the sorted array and use a two-pointer approach to find triplets that sum up to zero. 10 | - We use a HashSet to avoid duplicate triplets. 11 | - We add the valid triplets to a list and return the list as the result. 12 | 13 | ## Java Solution Code 14 | 15 | ```java 16 | import java.util.*; 17 | 18 | class Solution { 19 | public List> threeSum(int[] nums) { 20 | Arrays.sort(nums); 21 | List> triplets = new ArrayList<>(); 22 | Set> set = new HashSet<>(); 23 | int n = nums.length; 24 | 25 | for (int i = 0; i < n - 2; i++) { 26 | int j = i + 1, k = n - 1; 27 | while (j < k) { 28 | if (nums[i] + nums[j] + nums[k] == 0) { 29 | set.add(Arrays.asList(nums[i], nums[j], nums[k])); 30 | j++; 31 | k--; 32 | continue; 33 | } 34 | 35 | if (nums[j] + nums[k] + nums[i] > 0) 36 | k--; 37 | else 38 | j++; 39 | } 40 | } 41 | 42 | triplets.addAll(set); 43 | return triplets; 44 | } 45 | } 46 | ``` 47 | 48 | ## Complexity Analysis 49 | - **Time Complexity**: O(n^2), where n is the number of elements in the `nums` array due to the two-pointer approach. 50 | - **Space Complexity**: O(n) for the HashSet to store unique triplets. 51 | 52 | ## Code Explanation 53 | - We sort the `nums` array to simplify the search for triplets. 54 | - We iterate through the sorted array and use a two-pointer approach to find triplets. 55 | - We use a HashSet to avoid duplicate triplets in the result. 56 | - We add the valid triplets to a list and return it as the final result. 57 | -------------------------------------------------------------------------------- /Blind 75/12. Rotate Image.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 48: [Rotate Image](https://leetcode.com/problems/rotate-image/) 2 | 3 | ## Problem Description 4 | You are given an `n x n` 2D matrix representing an image, rotate the image by 90 degrees (clockwise). 5 | 6 | You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. 7 | 8 | ## Solution Approach 9 | - We perform the rotation in two steps: transpose and reverse. 10 | - First, we transpose the matrix by swapping elements across the diagonal. 11 | - Then, we reverse the elements in each row, effectively rotating the matrix by 90 degrees. 12 | 13 | ## Java Solution Code 14 | 15 | ```java 16 | class Solution { 17 | public void rotate(int[][] matrix) { 18 | // Transpose of Matrix 19 | for (int i = 0; i < matrix.length; i++) { 20 | for (int j = 0; j < matrix[0].length; j++) { 21 | if (i < j) { 22 | int temp = matrix[j][i]; 23 | matrix[j][i] = matrix[i][j]; 24 | matrix[i][j] = temp; 25 | } 26 | } 27 | } 28 | 29 | // Reverse the Column values 30 | for (int i = 0; i < matrix.length; i++) { 31 | int j = 0, k = matrix[0].length - 1; 32 | while (j < k) { 33 | int temp = matrix[i][j]; 34 | matrix[i][j] = matrix[i][k]; 35 | matrix[i][k] = temp; 36 | j++; 37 | k--; 38 | } 39 | } 40 | } 41 | } 42 | ``` 43 | 44 | ## Complexity Analysis 45 | - **Time Complexity**: O(n^2), where n is the number of rows or columns in the matrix. 46 | - **Space Complexity**: O(1), as we perform the rotation in-place without using any additional space. 47 | 48 | ## Code Explanation 49 | 1. We iterate through the upper triangular part of the matrix (above the diagonal) and swap the elements across the diagonal. This operation effectively transposes the matrix. 50 | 2. After transposing, we reverse the elements in each row by iterating over each row and swapping elements from both ends of the row. 51 | 3. The combined effect of transposing and reversing effectively rotates the image by 90 degrees clockwise. 52 | -------------------------------------------------------------------------------- /Blind 75/32. Valid Palindrome.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 125: [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/) 2 | 3 | ## Problem Description 4 | Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. 5 | 6 | ## Solution Approach 7 | - We use a two-pointer approach where we compare characters from the beginning and end of the string. 8 | - We ignore non-alphanumeric characters and compare only alphanumeric characters. 9 | - If the characters at the two pointers do not match, we return false. 10 | - If all characters match, we return true. 11 | 12 | ## Java Solution Code 13 | 14 | ```java 15 | class Solution { 16 | public boolean isPalindrome(String s) { 17 | int n = s.length(); 18 | int left = 0, right = n - 1; 19 | 20 | while (left < right) { 21 | char a = s.charAt(left); 22 | char b = s.charAt(right); 23 | 24 | if (!checkAlphaNumeric(a)) 25 | left++; 26 | else if (!checkAlphaNumeric(b)) 27 | right--; 28 | else if (Character.toLowerCase(a) != Character.toLowerCase(b)) 29 | return false; 30 | else { 31 | left++; 32 | right--; 33 | } 34 | } 35 | return true; 36 | } 37 | 38 | public boolean checkAlphaNumeric(char i) { 39 | return Character.isLetterOrDigit(i); 40 | } 41 | } 42 | ``` 43 | 44 | ## Complexity Analysis 45 | - **Time Complexity**: O(N), where N is the length of the string. We traverse the string once. 46 | - **Space Complexity**: O(1), constant space is used. 47 | 48 | ## Code Explanation 49 | 1. We define a function `isPalindrome` that checks if the given string is a palindrome. 50 | 2. We initialize two pointers, `left` and `right`, pointing to the beginning and end of the string, respectively. 51 | 3. While `left` is less than `right`, we compare characters at the two pointers. 52 | 4. We ignore non-alphanumeric characters using the `checkAlphaNumeric` function. 53 | 5. We compare characters at `left` and `right` ignoring cases. 54 | 6. If the characters do not match, we return false; otherwise, we continue traversing the string. 55 | 7. If all characters match, we return true. 56 | 57 | -------------------------------------------------------------------------------- /Blind 75/61. Encode and Decode Strings.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 271: [Encode and Decode Strings](https://leetcode.com/problems/encode-and-decode-strings/) 2 | 3 | ## Problem Description 4 | 5 | Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings. 6 | 7 | ## Solution Approach 8 | 9 | To encode the list of strings, we can concatenate each string with a special delimiter and encode it into a single string. To decode the string back into the list of strings, we split the encoded string using the delimiter and obtain the original list of strings. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | import java.util.*; 15 | 16 | public class Codec { 17 | 18 | // Encodes a list of strings to a single string. 19 | public String encode(List strs) { 20 | StringBuilder sb = new StringBuilder(); 21 | for (String s : strs) { 22 | sb.append(s.length()).append('/').append(s); 23 | } 24 | return sb.toString(); 25 | } 26 | 27 | // Decodes a single string to a list of strings. 28 | public List decode(String s) { 29 | List decodedStrings = new ArrayList<>(); 30 | int i = 0; 31 | while (i < s.length()) { 32 | int slashIndex = s.indexOf('/', i); 33 | int size = Integer.parseInt(s.substring(i, slashIndex)); 34 | i = slashIndex + 1; 35 | decodedStrings.add(s.substring(i, i + size)); 36 | i += size; 37 | } 38 | return decodedStrings; 39 | } 40 | } 41 | ``` 42 | 43 | ## Complexity Analysis 44 | 45 | - **Time Complexity**: 46 | - Encoding: O(n), where n is the total length of all strings in the list. 47 | - Decoding: O(n), where n is the length of the encoded string. 48 | - **Space Complexity**: O(n), where n is the total length of all strings in the list plus the size of the encoded string. 49 | 50 | ## Code Explanation 51 | 52 | - For encoding, we concatenate each string with its length followed by a delimiter ("/") and append it to a StringBuilder. 53 | - For decoding, we iterate through the encoded string, extract the length of each string, and use it to retrieve the original strings. 54 | - The decoded list of strings is returned. 55 | -------------------------------------------------------------------------------- /Blind 75/18. Insert Interval.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 57: [Insert Interval](https://leetcode.com/problems/insert-interval/) 2 | 3 | ## Problem Description 4 | Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). 5 | 6 | ## Solution Approach 7 | - We iterate through the existing intervals and perform the following steps: 8 | 1. Add non-overlapping intervals before the new interval. 9 | 2. Merge overlapping intervals with the new interval. 10 | 3. Add remaining non-overlapping intervals after the new interval. 11 | 12 | ## Java Solution Code 13 | 14 | ```java 15 | class Solution { 16 | public int[][] insert(int[][] intervals, int[] newInterval) { 17 | List mergedIntervals = new ArrayList<>(); 18 | int n = intervals.length, i = 0; 19 | 20 | // Add non-overlapping intervals before the new interval 21 | while (i < n && intervals[i][1] < newInterval[0]) { 22 | mergedIntervals.add(intervals[i]); 23 | i++; 24 | } 25 | 26 | // Merge overlapping intervals with the new interval 27 | while (i < n && intervals[i][0] <= newInterval[1]) { 28 | newInterval[0] = Math.min(newInterval[0], intervals[i][0]); 29 | newInterval[1] = Math.max(newInterval[1], intervals[i][1]); 30 | i++; 31 | } 32 | mergedIntervals.add(newInterval); 33 | 34 | // Add remaining non-overlapping intervals 35 | while (i < n) { 36 | mergedIntervals.add(intervals[i]); 37 | i++; 38 | } 39 | 40 | return mergedIntervals.toArray(new int[mergedIntervals.size()][]); 41 | } 42 | } 43 | ``` 44 | 45 | ## Complexity Analysis 46 | - **Time Complexity**: O(n), where n is the number of intervals. We iterate through the intervals once. 47 | - **Space Complexity**: O(n), for storing the merged intervals. 48 | 49 | ## Code Explanation 50 | 1. We iterate through the existing intervals and perform the following steps: 51 | - Add non-overlapping intervals before the new interval. 52 | - Merge overlapping intervals with the new interval. 53 | - Add remaining non-overlapping intervals after the new interval. 54 | 2. We use a list `mergedIntervals` to store the merged intervals. 55 | 3. Finally, we convert the list of merged intervals to a 2D array and return it. 56 | -------------------------------------------------------------------------------- /Blind 75/74. Palindromic Substrings.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 647: [Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings/) 2 | 3 | ## Problem Description 4 | 5 | Given a string `s`, return the number of palindromic substrings in it. A string is a palindrome when it reads the same backward as forward. 6 | 7 | ## Solution Approach 8 | 9 | To count the number of palindromic substrings in the given string `s`, we can use dynamic programming. We maintain a 2D array `dp[][]`, where `dp[i][j]` represents whether the substring from index `i` to index `j` is a palindrome or not. We then iterate through all substrings of `s` and count the number of palindromic substrings. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | import java.util.*; 15 | 16 | class Solution { 17 | public int solve(int i, int j, String s, int[][] dp) { 18 | if (i >= j) 19 | return dp[i][j] = 1; 20 | if (dp[i][j] != -1) 21 | return dp[i][j]; 22 | if (s.charAt(i) != s.charAt(j)) 23 | return dp[i][j] = 0; 24 | return dp[i][j] = solve(i + 1, j - 1, s, dp); 25 | } 26 | 27 | public int countSubstrings(String s) { 28 | int n = s.length(); 29 | int count = 0; 30 | int[][] dp = new int[n][n]; 31 | 32 | for (int[] row : dp) { 33 | Arrays.fill(row, -1); 34 | } 35 | 36 | for (int i = 0; i < n; i++) { 37 | for (int j = i; j < n; j++) { 38 | count += solve(i, j, s, dp); 39 | } 40 | } 41 | return count; 42 | } 43 | } 44 | ``` 45 | 46 | ## Complexity Analysis 47 | 48 | - **Time Complexity**: O(n^2), where n is the length of the input string `s`. We traverse through all substrings of `s` and check whether they are palindromes or not. 49 | - **Space Complexity**: O(n^2), the space used by the 2D array `dp[][]` to store the results of palindromic substrings for each substring of `s`. 50 | 51 | ## Code Explanation 52 | 53 | - We define a recursive function `solve` to determine whether a substring from index `i` to index `j` is a palindrome or not, using memoization. 54 | - We iterate through all substrings of `s` and count the number of palindromic substrings by calling the `solve` function. 55 | - Finally, we return the count of palindromic substrings in the given string `s`. 56 | 57 | -------------------------------------------------------------------------------- /Blind 75/30. Best Time to Buy and Sell Stock.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem [121]: [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) 2 | 3 | ## Problem Description 4 | You are given an array `prices` where `prices[i]` is the price of a given stock on the ith day. You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock. Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0. 5 | 6 | ## Solution Approach 7 | - We iterate through the prices array and keep track of the maximum profit we can achieve by buying on a given day and selling on a future day. 8 | - We update the maximum profit whenever we find a day where selling the stock at the current price would result in a higher profit than the previously calculated profit. 9 | 10 | ## Java Solution Code 11 | 12 | ```java 13 | class Solution { 14 | public int maxProfit(int[] prices) { 15 | int maxProfit = 0, i = 0, j = 1; 16 | while (j < prices.length) { 17 | if (prices[i] < prices[j]) 18 | profit = Math.max(maxProfit, prices[j] - prices[i]); 19 | else 20 | i = j; 21 | j++; 22 | } 23 | return maxProfit; 24 | } 25 | } 26 | ``` 27 | 28 | ## Complexity Analysis 29 | - **Time Complexity**: O(N), where N is the number of elements in the prices array. We iterate through the array once. 30 | - **Space Complexity**: O(1), constant extra space is used. 31 | 32 | ## Code Explanation 33 | 1. We initialize the profit variable to 0, which represents the maximum profit we can achieve. 34 | 2. We use two pointers, i and j, to traverse the prices array. We start with i at 0 and j at 1. 35 | 3. We iterate through the prices array and check if the current price (prices[j]) is greater than the price on the day we bought the stock (prices[i]). 36 | 4. If the current price is greater, we calculate the profit we can achieve by selling the stock on the current day (prices[j] - prices[i]) and update the maximum profit if needed. 37 | 5. If the current price is not greater, we update the buy day to the current day (i = j) and continue. 38 | 6. We continue this process until we reach the end of the prices array. 39 | 7. Finally, we return the maximum profit calculated during the traversal. 40 | -------------------------------------------------------------------------------- /Blind 75/17. Merge Intervals.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 56: [Merge Intervals](https://leetcode.com/problems/merge-intervals/) 3 | 4 | ## Problem Description 5 | Given an array of intervals where `intervals[i] = [start_i, end_i]`, merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input. 6 | 7 | ## Solution Approach 8 | - We sort the intervals based on the start times. 9 | - We iterate through the sorted intervals and merge overlapping intervals. 10 | - We maintain a list `mergedIntervals` to store the merged intervals. 11 | - For each interval, if it does not overlap with the previous merged interval, we add it to the list. 12 | - If it overlaps, we update the end time of the previous merged interval. 13 | - Finally, we convert the list to a 2D array and return it. 14 | 15 | ## Java Solution Code 16 | 17 | ```java 18 | class Solution { 19 | public int[][] merge(int[][] intervals) { 20 | Arrays.sort(intervals, (a, b) -> a[0] - b[0]); 21 | List mergedIntervals = new ArrayList<>(); 22 | for (int i = 0; i < intervals.length; i++) { 23 | int size = mergedIntervals.size(); 24 | if (mergedIntervals.isEmpty() || mergedIntervals.get(size - 1)[1] < intervals[i][0]) 25 | mergedIntervals.add(intervals[i]); 26 | else 27 | mergedIntervals.get(size - 1)[1] = Math.max(mergedIntervals.get(size - 1)[1], intervals[i][1]); 28 | } 29 | return mergedIntervals.toArray(new int[mergedIntervals.size()][2]); 30 | } 31 | } 32 | ``` 33 | 34 | ## Complexity Analysis 35 | - **Time Complexity**: O(n log n), where n is the number of intervals. Sorting the intervals takes O(n log n) time, and merging them takes linear time. 36 | - **Space Complexity**: O(n), for storing the merged intervals. 37 | 38 | ## Code Explanation 39 | 1. We sort the intervals based on the start times using `Arrays.sort()` and a custom comparator. 40 | 2. We iterate through the sorted intervals and merge overlapping intervals: 41 | - If the `mergedIntervals` list is empty or the end time of the previous merged interval is less than the start time of the current interval, we add the current interval to the list. 42 | - Otherwise, we update the end time of the previous merged interval if needed. 43 | 3. Finally, we convert the list of merged intervals to a 2D array and return it. 44 | -------------------------------------------------------------------------------- /Blind 75/75. Longest Common Subsequence.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 1143: [Longest Common Subsequence](https://leetcode.com/problems/longest-common-subsequence/) 2 | 3 | ## Problem Description 4 | 5 | Given two strings `text1` and `text2`, return the length of their longest common subsequence. A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters. 6 | 7 | ## Solution Approach 8 | 9 | To find the longest common subsequence between two strings `text1` and `text2`, we can use dynamic programming. We create a 2D array `dp[][]` where `dp[i][j]` represents the length of the longest common subsequence of substrings `text1.substring(0, i)` and `text2.substring(0, j)`. We iterate through the strings `text1` and `text2` and fill the `dp[][]` array accordingly. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public int longestCommonSubsequence(String text1, String text2) { 16 | int n = text1.length(); 17 | int m = text2.length(); 18 | 19 | int[][] dp = new int[n + 1][m + 1]; 20 | 21 | for (int i = 1; i <= n; i++) { 22 | for (int j = 1; j <= m; j++) { 23 | if (text1.charAt(i - 1) == text2.charAt(j - 1)) { 24 | dp[i][j] = 1 + dp[i - 1][j - 1]; 25 | } else { 26 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 27 | } 28 | } 29 | } 30 | 31 | return dp[n][m]; 32 | } 33 | } 34 | ``` 35 | 36 | ## Complexity Analysis 37 | 38 | - **Time Complexity**: O(n*m), where n is the length of `text1` and m is the length of `text2`. We traverse through each character of both strings once to fill the 2D array. 39 | - **Space Complexity**: O(n*m), the space used by the 2D array `dp[][]` to store the length of the longest common subsequence for each substring of `text1` and `text2`. 40 | 41 | ## Code Explanation 42 | 43 | - We create a 2D array `dp[][]` to store the length of the longest common subsequence for each prefix of `text1` and `text2`. 44 | - We iterate through both strings and fill the `dp[][]` array based on the characters being equal or not. 45 | - Finally, we return `dp[n][m]`, where n is the length of `text1` and m is the length of `text2`, representing the length of the longest common subsequence between the two strings. 46 | -------------------------------------------------------------------------------- /Blind 75/42. House Robber.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 198: [House Robber](https://leetcode.com/problems/house-robber/) 2 | 3 | ## Problem Description 4 | 5 | You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected, and it will automatically contact the police if two adjacent houses were broken into on the same night. Given an integer array `nums` representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police. 6 | 7 | ## Solution Approach 8 | 9 | We use dynamic programming to solve this problem. We define an array `dp` where `dp[i]` represents the maximum amount of money that can be robbed up to house `i`. We iterate through the array and calculate the maximum amount of money that can be robbed at each house based on the maximum of robbing the previous house or skipping the previous house and robbing the current house. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public int rob(int[] nums) { 16 | int n = nums.length; 17 | if (n == 1) 18 | return nums[0]; 19 | int[] dp = new int[n]; 20 | 21 | dp[0] = nums[0]; 22 | dp[1] = Math.max(nums[0], nums[1]); 23 | 24 | for (int i = 2; i < n; i++) { 25 | dp[i] = Math.max(dp[i - 1], nums[i] + dp[i - 2]); 26 | } 27 | 28 | return dp[n - 1]; 29 | } 30 | } 31 | ``` 32 | 33 | ## Complexity Analysis 34 | 35 | - **Time Complexity**: O(n), where n is the length of the input array `nums`. We iterate through the array once. 36 | - **Space Complexity**: O(n), where n is the length of the input array `nums`. We use an array of size n for dynamic programming. 37 | 38 | ## Code Explanation 39 | 40 | - We initialize an array `dp` to store the maximum amount of money that can be robbed up to house `i`. 41 | - We handle the base cases where if there is only one house, we return the money in that house. If there are two houses, we return the maximum amount of money between the two. 42 | - We iterate through the array and calculate the maximum amount of money that can be robbed at each house based on the maximum of robbing the previous house or skipping the previous house and robbing the current house. 43 | - We return the maximum amount of money that can be robbed from the last house. 44 | -------------------------------------------------------------------------------- /Blind 75/24. Decode Ways.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 91: [Decode Ways](https://leetcode.com/problems/decode-ways/) 2 | 3 | ## Problem Description 4 | A message containing letters from A-Z can be encoded into numbers using the following mapping: 5 | ``` 6 | 'A' -> "1" 7 | 'B' -> "2" 8 | ... 9 | 'Z' -> "26" 10 | ``` 11 | To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, "11106" can be mapped into: 12 | - "AAJF" with the grouping (1 1 10 6) 13 | - "KJF" with the grouping (11 10 6) 14 | 15 | Given a string `s` containing only digits, return the number of ways to decode it. 16 | 17 | ## Solution Approach 18 | - We use dynamic programming to keep track of the number of ways to decode the string up to each index. 19 | - We iterate through the string, updating the number of ways based on the current and previous characters. 20 | 21 | ## Java Solution Code 22 | 23 | ```java 24 | public class Solution { 25 | public int numDecodings(String s) { 26 | if (s == null || s.length() == 0 || s.charAt(0) == '0') { 27 | return 0; 28 | } 29 | 30 | int n = s.length(); 31 | int[] dp = new int[n + 1]; 32 | dp[0] = 1; 33 | dp[1] = 1; 34 | 35 | for (int i = 2; i <= n; ++i) { 36 | int oneDigit = s.charAt(i - 1) - '0'; 37 | int twoDigits = Integer.parseInt(s.substring(i - 2, i)); 38 | 39 | if (oneDigit != 0) { 40 | dp[i] += dp[i - 1]; 41 | } 42 | 43 | if (10 <= twoDigits && twoDigits <= 26) { 44 | dp[i] += dp[i - 2]; 45 | } 46 | } 47 | 48 | return dp[n]; 49 | } 50 | } 51 | ``` 52 | 53 | ## Complexity Analysis 54 | - **Time Complexity**: O(N), where N is the length of the input string `s`. We iterate through the string once to calculate the number of ways. 55 | - **Space Complexity**: O(N), for the dynamic programming array `dp` of size N+1. 56 | 57 | ## Code Explanation 58 | 1. We initialize an array `dp` to keep track of the number of ways to decode the string up to each index. 59 | 2. We iterate through the string starting from the second character. 60 | 3. For each character, we consider the single-digit and two-digit possibilities for decoding. 61 | 4. We update the `dp` array based on the decoding possibilities. 62 | 5. Finally, we return the number of ways to decode the entire string. 63 | -------------------------------------------------------------------------------- /Blind 75/02. Longest Substring Blind 75Without Repeating Characters.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 3: [Length of Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) 2 | 3 | ## Problem Description 4 | Given a string `s`, find the length of the longest substring without repeating characters. 5 | 6 | ## Solution Approach 7 | - We use a sliding window approach with two pointers `i` and `j` to track the current substring. 8 | - We use a HashMap to store the characters and their counts in the current substring. 9 | - We move the `j` pointer forward and update the HashMap. 10 | - If the current substring contains duplicate characters, we move the `i` pointer forward until the substring becomes valid again. 11 | - We update the longest substring length as we iterate through the string. 12 | 13 | ## Java Solution Code 14 | 15 | ```java 16 | import java.util.HashMap; 17 | 18 | class Solution { 19 | public int lengthOfLongestSubstring(String s) { 20 | HashMap map = new HashMap<>(); 21 | int i=0, j=0, n=s.length(); 22 | int longestSubstring = 0; 23 | 24 | while (j < n) { 25 | map.put(s.charAt(j), map.getOrDefault(s.charAt(j), 0) + 1); 26 | if (j - i + 1 == map.size()) { 27 | longestSubstring = Math.max(longestSubstring, j - i + 1); 28 | } else { 29 | while (j - i + 1 > map.size()) { 30 | map.put(s.charAt(i), map.get(s.charAt(i)) - 1); 31 | if (map.get(s.charAt(i)) == 0) { 32 | map.remove(s.charAt(i)); 33 | } 34 | i++; 35 | } 36 | longestSubstring = Math.max(longestSubstring, j - i + 1); 37 | } 38 | j++; 39 | } 40 | 41 | return longestSubstring; 42 | } 43 | } 44 | ``` 45 | 46 | # Complexity Analysis 47 | - **Time Complexity:** O(n), where n is the length of the input string. 48 | - **Space Complexity:** O(min(n, m)), where n is the length of the input string and m is the size of the character set (in this case, 26 for lowercase English letters). 49 | 50 | # Code Explanation 51 | - We iterate through the string using two pointers, i and j. 52 | - We update the HashMap to keep track of characters and their counts in the current substring. 53 | - If the current substring contains duplicate characters, we adjust the window size by moving the i pointer. 54 | -------------------------------------------------------------------------------- /Blind 75/68. Top K Frequent Elements.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 347: [Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/) 2 | 3 | ## Problem Description 4 | 5 | Given an integer array `nums` and an integer `k`, return the `k` most frequent elements. You may return the answer in any order. 6 | 7 | ## Solution Approach 8 | 9 | We use a HashMap to count the frequency of each number in the array. Then, we use a PriorityQueue to store elements based on their frequency. Finally, we extract the top k frequent elements from the PriorityQueue. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | import java.util.*; 15 | 16 | class Solution { 17 | public int[] topKFrequent(int[] nums, int k) { 18 | // Create a HashMap to store the frequency of each number 19 | Map frequencyMap = new HashMap<>(); 20 | 21 | // Count the frequency of each number 22 | for (int num : nums) { 23 | frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1); 24 | } 25 | 26 | // Create a PriorityQueue to store elements based on their frequency 27 | PriorityQueue pq = new PriorityQueue<>((a, b) -> Integer.compare(b[1], a[1])); 28 | 29 | // Add elements along with their frequency to the PriorityQueue 30 | for (int key : frequencyMap.keySet()) { 31 | pq.add(new int[]{key, frequencyMap.get(key)}); 32 | } 33 | 34 | // Extract top k frequent elements from the PriorityQueue 35 | int[] result = new int[k]; 36 | for (int i = 0; i < k; i++) { 37 | int[] element = pq.poll(); 38 | result[i] = element[0]; 39 | } 40 | 41 | return result; 42 | } 43 | } 44 | ``` 45 | 46 | ## Complexity Analysis 47 | 48 | - **Time Complexity**: O(n log k), where n is the length of the input array `nums` and k is the input parameter. Building the frequency map takes O(n) time, and extracting the top k frequent elements from the PriorityQueue takes O(k log k) time. 49 | - **Space Complexity**: O(n), where n is the length of the input array `nums`. We use a HashMap to store the frequency of each number and a PriorityQueue to store elements based on their frequency. 50 | 51 | ## Code Explanation 52 | 53 | - We count the frequency of each number in the array using a HashMap. 54 | - We store elements along with their frequency in a PriorityQueue, ordering them by frequency in descending order. 55 | - We extract the top k frequent elements from the PriorityQueue and return them. 56 | -------------------------------------------------------------------------------- /Blind 75/03. Longest Palindromic Substring.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 5: [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/) 2 | 3 | ## Problem Description 4 | Given a string s, return the longest palindromic substring in s. 5 | A palindrome is a word or phrase that is the same forwards and backward. 6 | ## Solution Approach 7 | - We use dynamic programming to solve the problem efficiently. 8 | - We initialize a 2D array `dp` to store the results of subproblems. 9 | - We iterate through the string and fill the `dp` array based on the palindromic property of substrings. 10 | - We return the longest palindromic substring found. 11 | 12 | ## Java Solution Code 13 | 14 | ```java 15 | class Solution { 16 | public String longestPalindrome(String s) { 17 | int n = s.length(); 18 | 19 | if (n <= 1) 20 | return s; 21 | 22 | int[][] dp = new int[n][n]; 23 | int maxLength = 1; 24 | int start = 0; 25 | 26 | // All substrings of length 1 are palindromes 27 | for (int i = 0; i < n; i++) 28 | dp[i][i] = 1; 29 | 30 | // Check for substrings of length 2 31 | for (int i = 0; i < n - 1; i++) { 32 | if (s.charAt(i) == s.charAt(i + 1)) { 33 | dp[i][i + 1] = 1; 34 | start = i; 35 | maxLength = 2; 36 | } 37 | } 38 | 39 | // Check for substrings of length greater than 2 40 | for (int length = 3; length <= n; length++) { 41 | for (int i = 0; i < n - length + 1; i++) { 42 | int j = i + length - 1; 43 | if (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1] == 1) { 44 | dp[i][j] = 1; 45 | if (length > maxLength) { 46 | start = i; 47 | maxLength = length; 48 | } 49 | } 50 | } 51 | } 52 | return s.substring(start, start + maxLength); 53 | } 54 | } 55 | ``` 56 | 57 | ## Complexity Analysis 58 | - **Time Complexity**: O(n^2), where n is the length of the input string `s`. 59 | - **Space Complexity**: O(n^2), where n is the length of the input string `s`. 60 | 61 | ## Code Explanation 62 | - We use dynamic programming to fill a 2D array `dp` to keep track of palindromic substrings. 63 | - We iterate through the string to find the longest palindromic substring by updating the `dp` array. 64 | - We return the substring based on the start index and maximum length found. 65 | 66 | -------------------------------------------------------------------------------- /Blind 75/13. Group Anagrams.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 49: [Group Anagrams](https://leetcode.com/problems/group-anagrams/) 2 | 3 | ## Problem Description 4 | Given an array of strings `strs`, group the anagrams together. You can return the answer in any order. 5 | 6 | An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once. 7 | 8 | ## Solution Approach 9 | - We use a HashMap to group anagrams. 10 | - For each string in the array, we sort its characters and use the sorted string as a key in the HashMap. 11 | - We add the original string to the list corresponding to its sorted key. 12 | - Finally, we return the values of the HashMap, which are the grouped anagrams. 13 | 14 | ## Java Solution Code 15 | 16 | ```java 17 | class Solution { 18 | public List> groupAnagrams(String[] strs) { 19 | HashMap> mp = new HashMap<>(); 20 | int n = strs.length; 21 | 22 | for (int i = 0; i < n; i++) { 23 | String temp = strs[i]; 24 | char[] arr = temp.toCharArray(); 25 | Arrays.sort(arr); 26 | String sorted = new String(arr); 27 | 28 | if (!mp.containsKey(sorted)) { 29 | mp.put(sorted, new ArrayList<>()); 30 | mp.get(sorted).add(temp); 31 | } else { 32 | mp.get(sorted).add(temp); 33 | } 34 | } 35 | return new ArrayList<>(mp.values()); 36 | } 37 | } 38 | ``` 39 | 40 | ## Complexity Analysis 41 | - **Time Complexity**: O(N * K * log K), where N is the number of strings in the array and K is the maximum length of a string. 42 | - We iterate through the array of strings, which takes O(N) time. 43 | - Sorting each string takes O(K * log K) time. 44 | - **Space Complexity**: O(N * K), where N is the number of strings in the array and K is the maximum length of a string. 45 | - We use extra space to store the HashMap, which can hold N * K key-value pairs. 46 | 47 | ## Code Explanation 48 | 1. We iterate through each string in the array `strs`. 49 | 2. For each string, we sort its characters and use the sorted string as a key in the HashMap `mp`. 50 | 3. If the sorted string is not already present in the HashMap, we create a new list and add the original string to it. 51 | 4. If the sorted string is already present, we retrieve the corresponding list from the HashMap and add the original string to it. 52 | 5. Finally, we return the values of the HashMap, which contain the grouped anagrams. 53 | -------------------------------------------------------------------------------- /Blind 75/62. Find Median from Data Stream.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 295: [Find Median from Data Stream](https://leetcode.com/problems/find-median-from-data-stream/) 2 | 3 | ## Problem Description 4 | 5 | Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value and the median is the mean of the two middle values. 6 | 7 | For example, for `arr = [2,3,4]`, the median is `3`. 8 | For example, for `arr = [2,3]`, the median is `(2 + 3) / 2 = 2.5`. 9 | 10 | Implement the MedianFinder class: 11 | 12 | - `MedianFinder()` initializes the MedianFinder object. 13 | - `void addNum(int num)` adds the integer `num` from the data stream to the data structure. 14 | - `double findMedian()` returns the median of all elements so far. Answers within 10^-5 of the actual answer will be accepted. 15 | 16 | 17 | ## Java Solution 18 | 19 | ```java 20 | import java.util.PriorityQueue; 21 | 22 | class MedianFinder { 23 | 24 | private PriorityQueue maxHeap; 25 | private PriorityQueue minHeap; 26 | 27 | public MedianFinder() { 28 | maxHeap = new PriorityQueue<>((a, b) -> b - a); 29 | minHeap = new PriorityQueue<>((a, b) -> a - b); 30 | } 31 | 32 | public void addNum(int num) { 33 | maxHeap.offer(num); 34 | minHeap.offer(maxHeap.poll()); 35 | 36 | if (maxHeap.size() < minHeap.size()) { 37 | maxHeap.offer(minHeap.poll()); 38 | } 39 | } 40 | 41 | public double findMedian() { 42 | if (maxHeap.size() == minHeap.size()) { 43 | return (maxHeap.peek() + minHeap.peek()) / 2.0; 44 | } else { 45 | return maxHeap.peek(); 46 | } 47 | } 48 | } 49 | ``` 50 | 51 | ## Complexity Analysis 52 | 53 | - **Time Complexity**: 54 | - Adding a number: O(log N) 55 | - Finding Median: O(1) 56 | - **Space Complexity**: O(N), where N is the number of elements in the data structure. 57 | 58 | ## Code Explanation 59 | 60 | - We use two heaps, a max heap for the left half of the elements and a min heap for the right half of the elements. 61 | - The max heap keeps track of the smaller half of the elements, and the min heap keeps track of the larger half. 62 | - When adding a number, we first add it to the max heap. We then move the maximum element from the max heap to the min heap to balance the elements. 63 | - The median is found based on the size of the two heaps. If they are equal, the median is the average of the two top elements. If the max heap is larger, the median is the top element of the max heap. 64 | -------------------------------------------------------------------------------- /Blind 75/25. Validate Binary Search Tree.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 98: [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/) 3 | 4 | ## Problem Description 5 | Given the root of a binary tree, determine if it is a valid binary search tree (BST). 6 | 7 | A valid BST is defined as follows: 8 | - The left subtree of a node contains only nodes with keys less than the node's key. 9 | - The right subtree of a node contains only nodes with keys greater than the node's key. 10 | - Both the left and right subtrees must also be binary search trees. 11 | 12 | ## Solution Approach 13 | - We use a recursive approach to check if each node in the tree satisfies the BST property. 14 | - At each node, we maintain the minimum and maximum limits for valid values. 15 | 16 | ## Java Solution Code 17 | 18 | ```java 19 | /** 20 | * Definition for a binary tree node. 21 | * public class TreeNode { 22 | * int val; 23 | * TreeNode left; 24 | * TreeNode right; 25 | * TreeNode() {} 26 | * TreeNode(int val) { this.val = val; } 27 | * TreeNode(int val, TreeNode left, TreeNode right) { 28 | * this.val = val; 29 | * this.left = left; 30 | * this.right = right; 31 | * } 32 | * } 33 | */ 34 | class Solution { 35 | public boolean isValidBST(TreeNode root) { 36 | return isValid(root, Long.MIN_VALUE, Long.MAX_VALUE); 37 | } 38 | 39 | boolean isValid(TreeNode root, long minLimit, long maxLimit) { 40 | if (root == null) 41 | return true; 42 | 43 | if (root.val <= minLimit || root.val >= maxLimit) 44 | return false; 45 | 46 | return isValid(root.left, minLimit, root.val) && isValid(root.right, root.val, maxLimit); 47 | } 48 | } 49 | ``` 50 | 51 | ## Complexity Analysis 52 | - **Time Complexity**: O(N), where N is the number of nodes in the binary tree. We visit each node once. 53 | - **Space Complexity**: O(N), for the recursive call stack, where N is the height of the binary tree in the worst case. 54 | 55 | ## Code Explanation 56 | 1. We use a recursive helper function `isValid` to check if each node and its subtrees satisfy the BST property. 57 | 2. At each node, we pass the minimum and maximum limits for valid values. 58 | 3. If the current node's value violates the limits, we return `false`. 59 | 4. Otherwise, we recursively check the left and right subtrees with updated limits. 60 | 5. If both subtrees return `true`, then the current subtree is a valid BST. 61 | 6. We repeat this process for each node in the tree, starting from the root. 62 | -------------------------------------------------------------------------------- /Blind 75/35. Word Break.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 139: [Word Break](https://leetcode.com/problems/word-break/) 2 | 3 | ## Problem Description 4 | 5 | Given a string `s` and a dictionary of strings `wordDict`, return true if `s` can be segmented into a space-separated sequence of one or more dictionary words. 6 | 7 | ## Solution Approach 8 | 9 | We use a dynamic programming approach to solve this problem. We iterate through the string `s` and check if substrings from the start of the string can be segmented into words from the dictionary. We use memoization to avoid recomputation of results for overlapping subproblems. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public boolean wordBreak(String s, List wordDict) { 16 | HashSet dictionary = new HashSet<>(wordDict); 17 | return findWord(0, s, dictionary, new Boolean[s.length()]); 18 | } 19 | 20 | boolean findWord(int start, String s, HashSet dictionary, Boolean[] memo) { 21 | if (start == s.length()) { 22 | return true; 23 | } 24 | 25 | if (memo[start] != null) { 26 | return memo[start]; 27 | } 28 | 29 | for (int end = start + 1; end <= s.length(); end++) { 30 | if (dictionary.contains(s.substring(start, end)) && findWord(end, s, dictionary, memo)) { 31 | return memo[start] = true; 32 | } 33 | } 34 | 35 | return memo[start] = false; 36 | } 37 | } 38 | ``` 39 | 40 | ## Complexity Analysis 41 | 42 | - **Time Complexity**: \(O(n^2)\), where \(n\) is the length of the string `s`. We use nested loops to iterate through the string and its substrings. 43 | - **Space Complexity**: \(O(n)\) for the memoization array. 44 | 45 | ## Code Explanation 46 | 47 | 1. We define a function `wordBreak` that checks if the string `s` can be segmented into words from the dictionary. 48 | 2. We initialize a HashSet `dictionary` with words from the `wordDict` list for efficient lookup. 49 | 3. We call the `findWord` function to recursively check if substrings of `s` starting from different indices can be segmented into words from the dictionary. 50 | 4. In the `findWord` function, we use memoization to avoid recomputation of results for overlapping subproblems. 51 | 5. We iterate through substrings of `s` starting from the `start` index and check if the substring exists in the dictionary. If it does, we recursively check the remaining substring. 52 | 6. If the substring can be segmented into words from the dictionary, we return true; otherwise, we return false. 53 | -------------------------------------------------------------------------------- /Blind 75/06. Remove Nth Node From End of List.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 19: [Remove Nth Node From End of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list/) 2 | 3 | ## Problem Description 4 | Given the head of a linked list, remove the n-th node from the end of the list and return its head. 5 | 6 | ## Solution Approach 7 | - We use a two-pointer approach to find the Nth node from the end of the list. 8 | - We initialize two pointers, `slow` and `fast`, both pointing to the head of the list. 9 | - We move the `fast` pointer n steps ahead. 10 | - Then, we move both pointers simultaneously until the `fast` pointer reaches the end of the list. 11 | - At this point, the `slow` pointer is at the Nth node from the end. 12 | - We skip the Nth node by adjusting the pointers. 13 | 14 | ## Java Solution Code 15 | 16 | ```java 17 | /** 18 | * Definition for singly-linked list. 19 | * public class ListNode { 20 | * int val; 21 | * ListNode next; 22 | * ListNode() {} 23 | * ListNode(int val) { this.val = val; } 24 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 25 | * } 26 | */ 27 | class Solution { 28 | public ListNode removeNthFromEnd(ListNode head, int n) { 29 | if (head == null || head.next == null) 30 | return null; 31 | ListNode slow = head, fast = head; 32 | 33 | // Move the fast pointer n steps ahead 34 | while (n != 0) { 35 | fast = fast.next; 36 | n--; 37 | } 38 | 39 | // If fast becomes null, the head needs to be removed 40 | if (fast == null) 41 | return head.next; 42 | 43 | // Move both pointers until fast reaches the end 44 | while (fast != null && fast.next != null) { 45 | slow = slow.next; 46 | fast = fast.next; 47 | } 48 | 49 | // Remove the Nth node by skipping it 50 | slow.next = slow.next.next; 51 | 52 | return head; 53 | } 54 | } 55 | ``` 56 | 57 | ## Complexity Analysis 58 | - **Time Complexity**: O(N), where N is the number of nodes in the linked list. 59 | - **Space Complexity**: O(1), as we use a constant amount of extra space for pointers. 60 | 61 | ## Code Explanation 62 | - We initialize two pointers, `slow` and `fast`, both pointing to the head of the list. 63 | - We move the `fast` pointer n steps ahead. 64 | - Then, we move both pointers simultaneously until the `fast` pointer reaches the end of the list. 65 | - At this point, the `slow` pointer is at the Nth node from the end. 66 | - We skip the Nth node by adjusting the pointers. 67 | -------------------------------------------------------------------------------- /Blind 75/08. Merge Two Sorted Lists.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem: [21. Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/) 2 | 3 | ## Problem Description 4 | Merge two sorted linked lists and return it as a sorted list. The list should be made by splicing together the nodes of the first two lists. 5 | 6 | ## Solution Approach 7 | We can merge two sorted linked lists iteratively by comparing the values of nodes and rearranging pointers. 8 | 9 | 1. **Initialization**: Initialize a dummy node `dummyHead` and a tail pointer `tail` pointing to the dummy node. 10 | 2. **Iterative Merge**: While both lists are not empty, compare the values of the current nodes `cur1` and `cur2`. 11 | - Attach the node with the smaller value to the `tail` and move the corresponding pointer forward. 12 | - Update the `tail` pointer to the newly attached node. 13 | 3. **Connect Remaining Nodes**: After one of the lists becomes empty, connect the remaining nodes of the non-empty list to the `tail`. 14 | 4. **Return Merged List**: Return `dummyHead.next` as the merged list. 15 | 16 | ## Java Solution Code 17 | 18 | ```java 19 | /** 20 | * Definition for singly-linked list. 21 | * public class ListNode { 22 | * int val; 23 | * ListNode next; 24 | * ListNode() {} 25 | * ListNode(int val) { this.val = val; } 26 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 27 | * } 28 | */ 29 | class Solution { 30 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 31 | if(l1 == null) 32 | return l2; 33 | else if(l2 == null) 34 | return l1; 35 | 36 | ListNode dummyHead = new ListNode(-1); 37 | ListNode tail = dummyHead; 38 | ListNode cur1 = l1; 39 | ListNode cur2 = l2; 40 | 41 | while(cur1 != null && cur2 != null) { 42 | if(cur1.val < cur2.val) { 43 | tail.next = cur1; 44 | cur1 = cur1.next; 45 | } else { 46 | tail.next = cur2; 47 | cur2 = cur2.next; 48 | } 49 | tail = tail.next; 50 | } 51 | 52 | if(cur1 == null) 53 | tail.next = cur2; 54 | else 55 | tail.next = cur1; 56 | 57 | return dummyHead.next; 58 | } 59 | } 60 | ``` 61 | 62 | ## Complexity Analysis 63 | - **Time Complexity**: O(m + n), where m and n are the lengths of the two input lists. 64 | - **Space Complexity**: O(1), constant extra space is used. 65 | 66 | ## Code Explanation 67 | - We iterate through the lists, comparing the values of nodes, and rearranging pointers to merge the lists in sorted order. 68 | -------------------------------------------------------------------------------- /Blind 75/49. House Robber II.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem: 213. [House Robber II](https://leetcode.com/problems/house-robber-ii/) 2 | 3 | ## Problem Description 4 | 5 | You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night. 6 | 7 | Given an integer array `nums` representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police. 8 | 9 | ## Solution Approach 10 | 11 | We can solve this problem using dynamic programming. Since the houses are arranged in a circle, we need to consider two cases: robbing the first house and not robbing the first house. We use two dynamic programming arrays to track the maximum amount of money we can rob in each case. 12 | 13 | ## Java Solution 14 | 15 | ```java 16 | import java.util.*; 17 | 18 | class Solution { 19 | public int rob(int[] nums) { 20 | int n = nums.length; 21 | if (n == 0) 22 | return 0; 23 | if (n == 1) 24 | return nums[0]; 25 | if (n == 2) 26 | return Math.max(nums[0], nums[1]); 27 | 28 | // Case 1 29 | int[] dp1 = new int[n + 1]; 30 | dp1[0] = nums[0]; 31 | dp1[1] = Math.max(nums[1], nums[0]); 32 | for (int i = 2; i < n - 1; i++) { 33 | dp1[i] = Math.max(dp1[i - 1], dp1[i - 2] + nums[i]); 34 | } 35 | 36 | // Case 2 37 | int[] dp2 = new int[n + 1]; 38 | dp2[0] = 0; 39 | dp2[1] = nums[1]; 40 | dp2[2] = Math.max(nums[2], nums[1]); 41 | for (int i = 3; i < n; i++) { 42 | dp2[i] = Math.max(dp2[i - 1], dp2[i - 2] + nums[i]); 43 | } 44 | 45 | // Final answer 46 | return Math.max(dp1[n - 2], dp2[n - 1]); 47 | } 48 | } 49 | ``` 50 | 51 | ## Complexity Analysis 52 | 53 | - **Time Complexity**: O(N), where N is the number of houses. 54 | - **Space Complexity**: O(N), where N is the number of houses. 55 | 56 | ## Code Explanation 57 | 58 | - We consider two cases: robbing the first house and not robbing the first house. 59 | - We use two dynamic programming arrays to track the maximum amount of money we can rob in each case. 60 | - We iterate through the array and calculate the maximum amount of money that can be robbed in each case. 61 | - Finally, we return the maximum amount of money between the two cases. 62 | -------------------------------------------------------------------------------- /Blind 75/15. Spiral Matrix.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 54: [Spiral Matrix](https://leetcode.com/problems/spiral-matrix/) 2 | 3 | ## Problem Description 4 | Given an `m x n` matrix, return all elements of the matrix in spiral order. 5 | 6 | ## Solution Approach 7 | - We use a four-pointer approach to traverse the matrix in a spiral order. 8 | - We maintain four pointers: `startRow`, `endRow`, `startCol`, and `endCol` to define the boundaries of the spiral. 9 | - We traverse the matrix in four directions: top, right, bottom, and left, adding elements to the result list as we go. 10 | 11 | ## Java Solution Code 12 | 13 | ```java 14 | import java.util.*; 15 | 16 | class Solution { 17 | public List spiralOrder(int[][] matrix) { 18 | int m = matrix.length; 19 | int n = matrix[0].length; 20 | int startRow = 0, endRow = m - 1, startCol = 0, endCol = n - 1; 21 | 22 | List spiralOrder = new ArrayList<>(); 23 | 24 | while (startRow <= endRow && startCol <= endCol) { 25 | // Traverse the top row from left to right 26 | for (int i = startCol; i <= endCol; i++) 27 | spiralOrder.add(matrix[startRow][i]); 28 | startRow++; 29 | 30 | // Traverse the right column from top to bottom 31 | for (int i = startRow; i <= endRow; i++) 32 | spiralOrder.add(matrix[i][endCol]); 33 | endCol--; 34 | 35 | // Traverse the bottom row from right to left 36 | if (startRow <= endRow) { 37 | for (int i = endCol; i >= startCol; i--) 38 | spiralOrder.add(matrix[endRow][i]); 39 | endRow--; 40 | } 41 | 42 | // Traverse the left column from bottom to top 43 | if (startCol <= endCol) { 44 | for (int i = endRow; i >= startRow; i--) 45 | spiralOrder.add(matrix[i][startCol]); 46 | startCol++; 47 | } 48 | } 49 | return spiralOrder; 50 | } 51 | } 52 | ``` 53 | 54 | ## Complexity Analysis 55 | - **Time Complexity**: O(m * n), where m is the number of rows and n is the number of columns in the matrix. 56 | - **Space Complexity**: O(m * n), where m * n is the size of the resulting list. 57 | 58 | ## Code Explanation 59 | 1. We initialize four pointers `startRow`, `endRow`, `startCol`, and `endCol` to define the boundaries of the spiral. 60 | 2. We traverse the matrix in a spiral order, adding elements to the `spiralOrder` list as we go. 61 | 3. We increment or decrement the pointers accordingly to move to the next direction. 62 | 4. Finally, we return the `spiralOrder` list as the result. 63 | -------------------------------------------------------------------------------- /Blind 75/37. Reorder List.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 143: [Reorder List](https://leetcode.com/problems/reorder-list/) 2 | 3 | ## Problem Description 4 | 5 | Given a singly linked list L: L0→L1→…→Ln-1→Ln, reorder it to: L0→Ln→L1→Ln-1→L2→Ln-2→… 6 | 7 | ## Solution Approach 8 | 9 | We use a three-step approach: 10 | 11 | 1. **Find the middle**: We use the fast-slow pointer technique to find the middle of the linked list. 12 | 2. **Reverse the second half**: We reverse the second half of the linked list. 13 | 3. **Merge the lists**: We merge the first half with the reversed second half by interweaving the nodes. 14 | 15 | ## Java Solution 16 | 17 | ```java 18 | /** 19 | * Definition for singly-linked list. 20 | * public class ListNode { 21 | * int val; 22 | * ListNode next; 23 | * ListNode() {} 24 | * ListNode(int val) { this.val = val; } 25 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 26 | * } 27 | */ 28 | class Solution { 29 | public void reorderList(ListNode head) { 30 | 31 | ListNode slow = head, fast = head; 32 | 33 | // Find the middle 34 | while (fast != null && fast.next != null) { 35 | fast = fast.next.next; 36 | slow = slow.next; 37 | } 38 | 39 | ListNode head2 = slow.next; 40 | slow.next = null; 41 | 42 | // Reverse the second half 43 | head2 = reverseList(head2); 44 | 45 | ListNode cur1 = head, cur2 = head2, temp1, temp2; 46 | // Merge the lists 47 | while (cur1 != null && cur2 != null) { 48 | temp1 = cur1.next; 49 | temp2 = cur2.next; 50 | cur1.next = cur2; 51 | cur2.next = temp1; 52 | cur2 = temp2; 53 | cur1 = temp1; 54 | } 55 | } 56 | 57 | ListNode reverseList(ListNode head) { 58 | ListNode prev = null; 59 | ListNode cur = head; 60 | ListNode temp; 61 | 62 | while (cur != null) { 63 | temp = cur.next; 64 | cur.next = prev; 65 | prev = cur; 66 | cur = temp; 67 | } 68 | 69 | return prev; 70 | } 71 | } 72 | ``` 73 | 74 | ## Complexity Analysis 75 | 76 | - **Time Complexity**: \(O(N)\), where \(N\) is the number of nodes in the linked list. We perform a linear scan of the list. 77 | - **Space Complexity**: \(O(1)\), constant extra space is used. 78 | 79 | ## Code Explanation 80 | 81 | 1. We find the middle of the linked list using the fast-slow pointer technique. 82 | 2. We reverse the second half of the linked list. 83 | 3. We merge the first half with the reversed second half by interweaving the nodes. 84 | -------------------------------------------------------------------------------- /Blind 75/21. Set Matrix Zeroes.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 73: [Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/) 2 | 3 | ## Problem Description 4 | Given an m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place. 5 | 6 | ## Solution Approach 7 | - We iterate through the matrix and mark the first element of each row and column as 0 if the corresponding element in the matrix is 0. 8 | - Then, we iterate through the matrix again and set the elements to 0 based on the marked rows and columns. 9 | - Finally, we handle the special case for the first row and first column. 10 | 11 | ## Java Solution Code 12 | 13 | ```java 14 | class Solution { 15 | public void setZeroes(int[][] matrix) { 16 | int n = matrix.length; 17 | int m = matrix[0].length; 18 | int col0 = 1; 19 | 20 | // Mark all elements 21 | for (int i = 0; i < n; i++) { 22 | for (int j = 0; j < m; j++) { 23 | if (matrix[i][j] == 0) { 24 | // Set 0th row 25 | matrix[i][0] = 0; 26 | // Set 0th column 27 | if (j == 0) 28 | col0 = 0; 29 | else 30 | matrix[0][j] = 0; 31 | } 32 | } 33 | } 34 | 35 | // Update matrix based on marked rows and columns 36 | for (int i = 1; i < n; i++) { 37 | for (int j = 1; j < m; j++) { 38 | if (matrix[i][0] == 0 || matrix[0][j] == 0) 39 | matrix[i][j] = 0; 40 | } 41 | } 42 | 43 | // Update first row 44 | if (matrix[0][0] == 0) { 45 | for (int j = 0; j < m; j++) 46 | matrix[0][j] = 0; 47 | } 48 | 49 | // Update first column 50 | if (col0 == 0) { 51 | for (int i = 0; i < n; i++) 52 | matrix[i][0] = 0; 53 | } 54 | } 55 | } 56 | ``` 57 | 58 | ## Complexity Analysis 59 | - **Time Complexity**: O(m * n), where m is the number of rows and n is the number of columns in the matrix. 60 | - **Space Complexity**: O(1), constant extra space is used. 61 | 62 | ## Code Explanation 63 | 1. We iterate through the matrix to mark the first element of each row and column as 0 if the corresponding element in the matrix is 0. 64 | 2. During this marking process, we also maintain a flag `col0` to determine if the first column needs to be zeroed out. 65 | 3. After marking, we iterate through the matrix again and set the elements to 0 based on the marked rows and columns. 66 | 4. Finally, we handle the special cases for the first row and first column by updating them accordingly. 67 | -------------------------------------------------------------------------------- /Blind 75/11. Combination Sum.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 39: [Combination Sum](https://leetcode.com/problems/combination-sum/) 2 | 3 | ## Problem Description 4 | Given an array of distinct integers `candidates` and a target integer `target`, return a list of all unique combinations of `candidates` where the chosen numbers sum to `target`. You may return the combinations in any order. 5 | 6 | The same number may be chosen from `candidates` an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different. 7 | 8 | It is guaranteed that the number of unique combinations that sum up to `target` is less than 150 combinations for the given input. 9 | 10 | ## Solution Approach 11 | - We use backtracking to generate all possible combinations of candidates that sum up to the target. 12 | - We recursively explore all possible combinations by trying each candidate starting from the current index. 13 | 14 | ## Java Solution Code 15 | 16 | ```java 17 | class Solution { 18 | public List> combinationSum(int[] candidates, int target) { 19 | List> uniqueCombinations = new ArrayList<>(); 20 | combinations(0, candidates, target, new ArrayList<>(), uniqueCombinations); 21 | return uniqueCombinations; 22 | } 23 | 24 | void combinations(int start, int[] candidates, int target, List temp, List> uniqueCombinations) { 25 | if (target == 0) 26 | uniqueCombinations.add(new ArrayList<>(temp)); 27 | if (target < 0) 28 | return; 29 | 30 | for (int i = start; i < candidates.length; i++) { 31 | temp.add(candidates[i]); 32 | combinations(i, candidates, target - candidates[i], temp, uniqueCombinations); 33 | temp.remove(temp.size() - 1); 34 | } 35 | } 36 | } 37 | ``` 38 | 39 | ## Complexity Analysis 40 | - **Time Complexity**: Exponential, as there can be many combinations generated. 41 | - **Space Complexity**: O(target), where target is the value we are trying to reach. 42 | 43 | ## Code Explanation 44 | 1. We initialize an empty list `uniqueCombinations` to store all unique combinations. 45 | 2. We call the `combinations` method to find all combinations, starting from index 0. 46 | 3. In the `combinations` method, if the target sum becomes 0, we add the current combination to `uniqueCombinations`. 47 | 4. We iterate through the candidates starting from the `start` index and recursively call the `combinations` method with updated parameters. 48 | 5. After processing a candidate, we backtrack by removing it from the `temp` list to explore other combinations. 49 | 50 | This approach ensures that we find all possible unique combinations that sum up to the target. 51 | -------------------------------------------------------------------------------- /Blind 75/65. Coin Change.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 322: [Coin Change](https://leetcode.com/problems/coin-change/) 2 | 3 | ## Problem Description 4 | 5 | You are given coins of different denominations and a total amount of money `amount`. Write a function to compute the minimum number of coins needed to make up that amount. If that amount of money cannot be made up by any combination of the coins, return `-1`. 6 | 7 | ## Solution Approach 8 | 9 | We can solve this problem using dynamic programming. We create a 2D array `dp`, where `dp[i][j]` represents the minimum number of coins needed to make up amount `j` using the first `i` coins. We fill in the array iteratively based on the current coin's value and the previously computed values. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public int coinChange(int[] coins, int amount) { 16 | int n = coins.length; 17 | int[][] dp = new int[n + 1][amount + 1]; 18 | int maxValue = Integer.MAX_VALUE - 1; 19 | 20 | for (int i = 0; i <= n; i++) 21 | dp[i][0] = 0; 22 | 23 | for (int j = 0; j <= amount; j++) { 24 | if ((j % coins[0]) == 0) 25 | dp[1][j] = j / coins[0]; 26 | else 27 | dp[1][j] = maxValue; 28 | } 29 | 30 | for (int i = 2; i <= n; i++) { 31 | for (int j = 1; j <= amount; j++) { 32 | if (coins[i - 1] <= j) { 33 | dp[i][j] = Math.min(dp[i - 1][j], 1 + dp[i][j - coins[i - 1]]); 34 | } else { 35 | dp[i][j] = dp[i - 1][j]; 36 | } 37 | } 38 | } 39 | 40 | return dp[n][amount] == maxValue ? -1 : dp[n][amount]; 41 | } 42 | } 43 | ``` 44 | 45 | ## Complexity Analysis 46 | 47 | - **Time Complexity**: O(n * amount), where n is the number of coins and amount is the target amount. We iterate through a 2D array of size n x amount. 48 | - **Space Complexity**: O(n * amount), where n is the number of coins and amount is the target amount. We use a 2D array of size n x amount for dynamic programming. 49 | 50 | ## Code Explanation 51 | 52 | - We initialize a 2D array `dp` to store the minimum number of coins needed to make up each amount. 53 | - We fill the first row with 0, as no coins are needed to make up amount 0. 54 | - We fill the first column with the maximum value if the amount is not divisible by the first coin, and the number of coins needed to make up the amount divided by the first coin otherwise. 55 | - We iterate through the remaining cells of the array and fill them based on the current coin's value and the previously computed values. 56 | - The result is stored in the bottom-right cell of the array, representing the minimum number of coins needed to make up the target amount. 57 | -------------------------------------------------------------------------------- /Blind 75/73. Subtree of Another Tree.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 572: [Subtree of Another Tree](https://leetcode.com/problems/subtree-of-another-tree/) 2 | 3 | ## Problem Description 4 | 5 | Given the roots of two binary trees `root` and `subRoot`, return true if `subRoot` is a subtree of `root`, otherwise return false. A subtree of a binary tree `tree` is a tree that consists of a node in `tree` and all of this node's descendants. The tree `tree` could also be considered as a subtree of itself. 6 | 7 | ## Solution Approach 8 | 9 | To solve this problem, we can perform a depth-first search (DFS) on the main tree (`root`) and at each node, check if the subtree rooted at that node is identical to the given `subRoot` tree. We continue this process recursively until we find a match or exhaust all nodes in the main tree. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | /** 15 | * Definition for a binary tree node. 16 | * public class TreeNode { 17 | * int val; 18 | * TreeNode left; 19 | * TreeNode right; 20 | * TreeNode() {} 21 | * TreeNode(int val) { this.val = val; } 22 | * TreeNode(int val, TreeNode left, TreeNode right) { 23 | * this.val = val; 24 | * this.left = left; 25 | * this.right = right; 26 | * } 27 | * } 28 | */ 29 | class Solution { 30 | boolean isSubtreeFound = false; 31 | 32 | public boolean isSubtree(TreeNode root, TreeNode subRoot) { 33 | if (root == null) { 34 | return false; 35 | } 36 | if (isSameTree(root, subRoot)) { 37 | return true; 38 | } 39 | 40 | return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); 41 | } 42 | 43 | boolean isSameTree(TreeNode nodeA, TreeNode nodeB) { 44 | if (nodeA == null && nodeB == null) { 45 | return true; 46 | } 47 | 48 | if (nodeA == null || nodeB == null) { 49 | return false; 50 | } 51 | 52 | return nodeA.val == nodeB.val && isSameTree(nodeA.left, nodeB.left) && isSameTree(nodeA.right, nodeB.right); 53 | } 54 | } 55 | ``` 56 | 57 | ## Complexity Analysis 58 | 59 | - **Time Complexity**: O(m * n) where m is the number of nodes in the main tree and n is the number of nodes in the subtree. In the worst case, we traverse the main tree and at each node, we traverse the subtree to check for equality. 60 | - **Space Complexity**: O(h) where h is the height of the main tree. The space complexity is determined by the recursion stack during the depth-first search. 61 | 62 | ## Code Explanation 63 | 64 | - We perform a depth-first search (DFS) on the main tree (`root`) and at each node, check if the subtree rooted at that node is identical to the given `subRoot` tree. 65 | - We continue this process recursively until we find a match or exhaust all nodes in the main tree. 66 | 67 | -------------------------------------------------------------------------------- /Blind 75/66. Number of Connected Components in an Undirected Graph.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 323: [Number of Connected Components in an Undirected Graph](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/) 2 | 3 | ## Problem Description 4 | 5 | Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to find the number of connected components in an undirected graph. 6 | 7 | ## Solution Approach 8 | 9 | We can solve this problem using Depth-First Search (DFS) or Breadth-First Search (BFS) algorithms. We traverse through the graph starting from each unvisited node and mark all connected nodes as visited. The number of times we perform this operation gives us the count of connected components in the graph. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Solution { 15 | public int countComponents(int n, int[][] edges) { 16 | boolean[] visited = new boolean[n]; 17 | List> adjacencyList = new ArrayList<>(); 18 | 19 | for (int i = 0; i < n; i++) 20 | adjacencyList.add(new ArrayList<>()); 21 | 22 | // Building adjacency list 23 | for (int[] edge : edges) { 24 | adjacencyList.get(edge[0]).add(edge[1]); 25 | adjacencyList.get(edge[1]).add(edge[0]); 26 | } 27 | 28 | int count = 0; 29 | for (int i = 0; i < n; i++) { 30 | if (!visited[i]) { 31 | dfs(i, adjacencyList, visited); 32 | count++; 33 | } 34 | } 35 | 36 | return count; 37 | } 38 | 39 | private void dfs(int node, List> adjacencyList, boolean[] visited) { 40 | visited[node] = true; 41 | for (int neighbor : adjacencyList.get(node)) { 42 | if (!visited[neighbor]) { 43 | dfs(neighbor, adjacencyList, visited); 44 | } 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | ## Complexity Analysis 51 | 52 | - **Time Complexity**: O(V + E), where V is the number of vertices (nodes) and E is the number of edges in the graph. We traverse each node and edge once during DFS. 53 | - **Space Complexity**: O(V + E), where V is the number of vertices (nodes) and E is the number of edges in the graph. We use additional space for the adjacency list and the visited array. 54 | 55 | ## Code Explanation 56 | 57 | - We initialize a boolean array `visited` to keep track of visited nodes. 58 | - We create an adjacency list to represent the graph. 59 | - We traverse through the graph using DFS starting from each unvisited node. 60 | - During DFS traversal, we mark all connected nodes as visited. 61 | - Each DFS traversal corresponds to a connected component, and we increment the count accordingly. 62 | - Finally, we return the count of connected components in the graph. 63 | -------------------------------------------------------------------------------- /Blind 75/58. Graph Valid Tree.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 261: [Graph Valid Tree](https://leetcode.com/problems/graph-valid-tree/) 2 | 3 | ## Problem Description 4 | 5 | Given `n` nodes labeled from `0` to `n - 1` and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree. 6 | 7 | ## Solution Approach 8 | 9 | To determine if a graph is a valid tree, we need to check two conditions: 10 | 1. The graph must be fully connected. 11 | 2. There should be no cycles present in the graph. 12 | 13 | We can use Depth-First Search (DFS) or Breadth-First Search (BFS) to traverse the graph and check these conditions. 14 | 15 | ## Java Solution 16 | 17 | ```java 18 | import java.util.*; 19 | 20 | class Solution { 21 | public boolean validTree(int n, int[][] edges) { 22 | Map> graph = new HashMap<>(); 23 | for (int i = 0; i < n; i++) { 24 | graph.put(i, new ArrayList<>()); 25 | } 26 | for (int[] edge : edges) { 27 | int u = edge[0], v = edge[1]; 28 | graph.get(u).add(v); 29 | graph.get(v).add(u); 30 | } 31 | 32 | boolean[] visited = new boolean[n]; 33 | if (hasCycle(graph, visited, 0, -1)) { 34 | return false; // There is a cycle, so it's not a tree 35 | } 36 | 37 | for (boolean visit : visited) { 38 | if (!visit) { 39 | return false; // There is a disconnected node, so it's not a tree 40 | } 41 | } 42 | return true; 43 | } 44 | 45 | private boolean hasCycle(Map> graph, boolean[] visited, int node, int parent) { 46 | visited[node] = true; 47 | for (int neighbor : graph.get(node)) { 48 | if (!visited[neighbor]) { 49 | if (hasCycle(graph, visited, neighbor, node)) { 50 | return true; 51 | } 52 | } else if (neighbor != parent) { 53 | return true; 54 | } 55 | } 56 | return false; 57 | } 58 | } 59 | ``` 60 | 61 | ## Complexity Analysis 62 | 63 | - **Time Complexity**: O(V + E), where V is the number of nodes (vertices) and E is the number of edges in the graph. 64 | - **Space Complexity**: O(V + E), where V is the number of nodes (vertices) and E is the number of edges in the graph. We use a HashMap to represent the graph and boolean arrays to track visited nodes. 65 | 66 | ## Code Explanation 67 | 68 | - We create a graph using a HashMap, where each node maps to a list of its neighbors. 69 | - We perform a Depth-First Search (DFS) traversal of the graph to check for cycles and disconnected nodes. 70 | - If we encounter a cycle or disconnected node during the traversal, we return false indicating that the graph is not a valid tree. Otherwise, we return true. 71 | -------------------------------------------------------------------------------- /Blind 75/47. Design Add and Search Words Data Structure.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 211: [Design Add and Search Words Data Structure](https://leetcode.com/problems/design-add-and-search-words-data-structure/) 2 | 3 | ## Problem Description 4 | 5 | Design a data structure that supports the following two operations: 6 | 7 | - `void addWord(word)`: Adds a word into the data structure. 8 | - `bool search(word)`: Returns true if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. 9 | 10 | ## Solution Approach 11 | 12 | We implement a Trie data structure where each node contains an array of child nodes representing each character in the alphabet. We define methods to add a word into the trie and search for a word in the trie, where the word may contain the dot character '.' to represent any one letter. 13 | 14 | ## Java Solution 15 | 16 | ```java 17 | class WordDictionary { 18 | private WordDictionary[] children; 19 | boolean isEndOfWord; 20 | 21 | public WordDictionary() { 22 | children = new WordDictionary[26]; 23 | isEndOfWord = false; 24 | } 25 | 26 | public void addWord(String word) { 27 | WordDictionary curr = this; 28 | for(char c: word.toCharArray()){ 29 | if(curr.children[c - 'a'] == null) 30 | curr.children[c - 'a'] = new WordDictionary(); 31 | curr = curr.children[c - 'a']; 32 | } 33 | curr.isEndOfWord = true; 34 | } 35 | 36 | public boolean search(String word) { 37 | WordDictionary curr = this; 38 | for(int i = 0; i < word.length(); ++i){ 39 | char c = word.charAt(i); 40 | if(c == '.'){ 41 | for(WordDictionary ch: curr.children) 42 | if(ch != null && ch.search(word.substring(i+1))) return true; 43 | return false; 44 | } 45 | if(curr.children[c - 'a'] == null) return false; 46 | curr = curr.children[c - 'a']; 47 | } 48 | return curr != null && curr.isEndOfWord; 49 | } 50 | } 51 | ``` 52 | 53 | ## Complexity Analysis 54 | 55 | - **Time Complexity**: 56 | - `addWord`: O(n), where n is the length of the word being added. 57 | - `search`: O(n), where n is the length of the word being searched. 58 | - **Space Complexity**: O(m*n), where m is the number of words and n is the average length of the words. 59 | 60 | ## Code Explanation 61 | 62 | - We define a WordDictionary class with methods to add a word and search for a word. 63 | - Each node in the trie contains an array of child nodes representing each character in the alphabet. 64 | - We recursively add each character of the word into the trie starting from the root node. 65 | - We recursively search for each character of the word in the trie starting from the root node, allowing '.' to represent any one letter. 66 | -------------------------------------------------------------------------------- /Blind 75/09. Merge k Sorted Lists.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 23: [Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/) 2 | 3 | ## Problem Description 4 | Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity without examples and constraints. 5 | 6 | ## Solution Approach 7 | - We merge the k sorted linked lists by iterating through each list and merging them two at a time. 8 | - We repeatedly merge two lists until we have merged all the lists into one sorted list. 9 | 10 | ## Java Solution Code 11 | 12 | ```java 13 | /** 14 | * Definition for singly-linked list. 15 | * public class ListNode { 16 | * int val; 17 | * ListNode next; 18 | * ListNode() {} 19 | * ListNode(int val) { this.val = val; } 20 | * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 21 | * } 22 | */ 23 | class Solution { 24 | public ListNode mergeKLists(ListNode[] lists) { 25 | int n = lists.length; 26 | ListNode newHead = null; 27 | for (int i = 0; i < n; i++) 28 | newHead = mergeTwoLists(newHead, lists[i]); 29 | 30 | return newHead; 31 | } 32 | 33 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 34 | if (l1 == null) 35 | return l2; 36 | else if (l2 == null) 37 | return l1; 38 | 39 | ListNode head = null, tail = null, cur1 = l1, cur2 = l2; 40 | if (cur1.val < cur2.val) { 41 | head = cur1; 42 | tail = cur1; 43 | cur1 = cur1.next; 44 | } else { 45 | head = cur2; 46 | tail = cur2; 47 | cur2 = cur2.next; 48 | } 49 | 50 | while (cur1 != null && cur2 != null) { 51 | if (cur1.val < cur2.val) { 52 | tail.next = cur1; 53 | tail = tail.next; 54 | cur1 = cur1.next; 55 | } else { 56 | tail.next = cur2; 57 | tail = tail.next; 58 | cur2 = cur2.next; 59 | } 60 | } 61 | 62 | if (cur1 == null) 63 | tail.next = cur2; 64 | else 65 | tail.next = cur1; 66 | 67 | return head; 68 | } 69 | } 70 | ``` 71 | 72 | ## Code Explanation 73 | 1. We define a class `Solution` that contains the method `mergeKLists` to merge k sorted lists. 74 | 2. In the `mergeKLists` method, we iterate through each list and merge them two at a time using the `mergeTwoLists` method. 75 | 3. The `mergeTwoLists` method merges two sorted linked lists and returns the merged list. 76 | 4. We maintain pointers `head` and `tail` to keep track of the merged list while iterating through the two lists. 77 | 5. We compare the values of the current nodes in the two lists and append the smaller node to the merged list. 78 | 6. Finally, we return the merged list. 79 | 80 | This approach ensures that we merge all k sorted lists into one sorted list. 81 | -------------------------------------------------------------------------------- /Blind 75/45. Course Schedule.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 207: [Course Schedule](https://leetcode.com/problems/course-schedule/) 2 | 3 | ## Problem Description 4 | 5 | There are a total of `numCourses` courses you have to take, labeled from `0` to `numCourses - 1`. You are given an array `prerequisites` where `prerequisites[i] = [ai, bi]` indicates that you must take course `bi` first if you want to take course `ai`. 6 | 7 | Return `true` if you can finish all courses. Otherwise, return `false`. 8 | 9 | ## Solution Approach 10 | 11 | We can solve this problem using depth-first search (DFS) with a topological sort approach. We create an adjacency list representing the course prerequisites. Then, we perform DFS traversal on each course to check for cycles in the graph. If a cycle is found, it means the courses cannot be completed, and we return `false`. Otherwise, we return `true`. 12 | 13 | ## Java Solution 14 | 15 | ```java 16 | class Solution { 17 | public boolean canFinish(int numCourses, int[][] prerequisites) { 18 | ArrayList> adj = new ArrayList<>(); 19 | for (int i = 0; i < numCourses; i++) 20 | adj.add(new ArrayList<>()); 21 | 22 | for (int i = 0; i < prerequisites.length; i++) 23 | adj.get(prerequisites[i][0]).add(prerequisites[i][1]); 24 | 25 | int[] topo = new int[numCourses]; 26 | boolean[] visited = new boolean[numCourses]; 27 | 28 | for (int i = 0; i < numCourses; i++) { 29 | if (!visited[i]) { 30 | if (dfs(i, adj, visited, topo)) 31 | return false; 32 | } 33 | } 34 | 35 | return true; 36 | } 37 | 38 | boolean dfs(int node, ArrayList> adj, boolean[] visited, int[] topo) { 39 | visited[node] = true; 40 | topo[node] = 1; 41 | 42 | for (int x : adj.get(node)) { 43 | if (!visited[x]) { 44 | if (dfs(x, adj, visited, topo)) 45 | return true; 46 | } else if (topo[x] == 1) 47 | return true; 48 | } 49 | 50 | topo[node] = 0; 51 | return false; 52 | } 53 | } 54 | ``` 55 | 56 | ## Complexity Analysis 57 | 58 | - **Time Complexity**: O(V + E), where V is the number of courses (vertices) and E is the number of dependencies (edges) in the graph. We visit each course and its dependencies once. 59 | - **Space Complexity**: O(V + E), where V is the number of courses and E is the number of dependencies. We use space for the adjacency list, visited array, and topo array. 60 | 61 | ## Code Explanation 62 | 63 | 1. We initialize an adjacency list to represent the prerequisites of each course. 64 | 2. We perform DFS traversal on each course to check for cycles in the graph. 65 | 3. If a cycle is found during the DFS traversal, we return `false` indicating that the courses cannot be completed. 66 | 4. Otherwise, we return `true` indicating that all courses can be finished. 67 | -------------------------------------------------------------------------------- /Blind 75/34. Clone Graph.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 133: [Clone Graph](https://leetcode.com/problems/clone-graph/) 2 | 3 | ## Problem Description 4 | 5 | Given a reference of a node in a connected undirected graph, return a deep copy (clone) of the graph. 6 | 7 | Each node in the graph contains a val (int) and a list (List[Node]) of its neighbors. 8 | 9 | ## Solution Approach 10 | 11 | To clone the graph, we perform a depth-first search (DFS) traversal of the original graph. We use a HashMap to keep track of visited nodes and their corresponding cloned nodes. At each step of the DFS traversal, we create a new node and add it to the HashMap. We then recursively traverse the neighbors of the current node and add them to the neighbor list of the cloned node. Finally, we return the cloned graph. 12 | 13 | ## Java Solution 14 | 15 | ```java 16 | /* 17 | // Definition for a Node. 18 | class Node { 19 | public int val; 20 | public List neighbors; 21 | public Node() { 22 | val = 0; 23 | neighbors = new ArrayList(); 24 | } 25 | public Node(int _val) { 26 | val = _val; 27 | neighbors = new ArrayList(); 28 | } 29 | public Node(int _val, ArrayList _neighbors) { 30 | val = _val; 31 | neighbors = _neighbors; 32 | } 33 | } 34 | */ 35 | 36 | class Solution { 37 | public Node cloneGraph(Node node) { 38 | HashMap visited = new HashMap<>(); 39 | return cloneGraphDFSHelper(node, visited); 40 | } 41 | 42 | private Node cloneGraphDFSHelper(Node cur, HashMap visited) { 43 | if (cur == null) { 44 | return null; 45 | } 46 | if (visited.containsKey(cur)) { 47 | return visited.get(cur); 48 | } 49 | 50 | Node newNode = new Node(cur.val); 51 | visited.put(cur, newNode); 52 | 53 | for (Node n : cur.neighbors) { 54 | newNode.neighbors.add(cloneGraphDFSHelper(n, visited)); 55 | } 56 | 57 | return newNode; 58 | } 59 | } 60 | ``` 61 | 62 | ## Complexity Analysis 63 | 64 | - **Time Complexity**: \(O(V + E)\), where \(V\) is the number of nodes (vertices) and \(E\) is the number of edges in the graph. 65 | - **Space Complexity**: \(O(V)\) for the HashMap to store visited nodes. 66 | 67 | ## Code Explanation 68 | 69 | 1. We define a function `cloneGraph` that clones the given graph. 70 | 2. We initialize an empty HashMap `visited` to keep track of visited nodes and their clones. 71 | 3. We call the DFS helper function `cloneGraphDFSHelper` with the starting node and the `visited` HashMap. 72 | 4. In the DFS helper function, if the current node is null, we return null. 73 | 5. If the current node is already visited, we return its clone from the `visited` HashMap. 74 | 6. Otherwise, we create a new node with the current node's value and add it to the `visited` HashMap. 75 | 7. We then iterate through the neighbors of the current node and recursively clone each neighbor, adding it to the cloned node's neighbors list. 76 | 8. Finally, we return the cloned graph. 77 | -------------------------------------------------------------------------------- /Blind 75/23. Word Search.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 79: [Word Search](https://leetcode.com/problems/word-search/) 2 | 3 | ## Problem Description 4 | Given an `m x n` grid of characters `board` and a string `word`, return `true` if `word` exists in the grid. The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once. 5 | 6 | ## Solution Approach 7 | - We perform a Depth-First Search (DFS) traversal starting from each cell in the grid. 8 | - At each cell, we explore the neighboring cells to see if they form the given word. 9 | - We mark visited cells to avoid revisiting them during the DFS traversal. 10 | 11 | ## Java Solution Code 12 | 13 | ```java 14 | class Solution { 15 | char matrix[][]; 16 | char letters[]; 17 | boolean visited[][]; 18 | 19 | public boolean exist(char[][] board, String word) { 20 | letters = word.toCharArray(); 21 | matrix = board; 22 | int n = matrix.length, m = matrix[0].length; 23 | 24 | for (int i = 0; i < n; i++) { 25 | for (int j = 0; j < m; j++) { 26 | if (matrix[i][j] == letters[0]) { 27 | visited = new boolean[n][m]; 28 | if (dfs(i, j, 0, visited)) 29 | return true; 30 | } 31 | } 32 | } 33 | return false; 34 | } 35 | 36 | boolean dfs(int i, int j, int index, boolean visited[][]) { 37 | if (index >= letters.length) 38 | return true; 39 | if (i < 0 || j < 0 || i >= matrix.length || j >= matrix[0].length || visited[i][j]) 40 | return false; 41 | if (matrix[i][j] != letters[index]) 42 | return false; 43 | 44 | visited[i][j] = true; 45 | boolean bottom = dfs(i + 1, j, index + 1, visited); 46 | boolean right = dfs(i, j + 1, index + 1, visited); 47 | boolean top = dfs(i - 1, j, index + 1, visited); 48 | boolean left = dfs(i, j - 1, index + 1, visited); 49 | visited[i][j] = false; 50 | 51 | return top || right || bottom || left; 52 | } 53 | } 54 | ``` 55 | 56 | ## Complexity Analysis 57 | - **Time Complexity**: O(N * M * 3^L), where N and M are the dimensions of the grid, and L is the length of the word. We explore up to 3 directions (excluding the cell we came from) for each cell in the grid, and there are N * M starting cells. 58 | - **Space Complexity**: O(N * M), for the boolean array to mark visited cells. 59 | 60 | ## Code Explanation 61 | 1. We iterate through each cell in the grid. 62 | 2. If the current cell contains the first character of the word, we initiate a Depth-First Search (DFS) from that cell. 63 | 3. During the DFS traversal, we explore neighboring cells in all four directions (up, down, left, right) to find the characters of the word. 64 | 4. We mark visited cells to avoid revisiting them during the DFS traversal. 65 | 5. If we find the complete word while exploring the neighboring cells, we return true. Otherwise, we return false. 66 | -------------------------------------------------------------------------------- /Blind 75/31. Binary Tree Maximum Path Sum.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 124: [Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/) 3 | 4 | ## Problem Description 5 | Given a non-empty binary tree, find the maximum path sum. For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root. 6 | 7 | ## Solution Approach 8 | - We recursively traverse the binary tree in a depth-first manner. 9 | - At each node, we calculate the maximum path sum that passes through that node and update the global maximum path sum accordingly. 10 | - We return the maximum path sum found after traversing the entire tree. 11 | 12 | ## Java Solution Code 13 | 14 | ```java 15 | /** 16 | * Definition for a binary tree node. 17 | * public class TreeNode { 18 | * int val; 19 | * TreeNode left; 20 | * TreeNode right; 21 | * TreeNode() {} 22 | * TreeNode(int val) { this.val = val; } 23 | * TreeNode(int val, TreeNode left, TreeNode right) { 24 | * this.val = val; 25 | * this.left = left; 26 | * this.right = right; 27 | * } 28 | * } 29 | */ 30 | class Solution { 31 | int maxPath = Integer.MIN_VALUE; 32 | 33 | public int maxPathSum(TreeNode root) { 34 | if (root == null) 35 | return 0; 36 | 37 | findMaxPathSum(root); 38 | return maxPath; 39 | } 40 | 41 | int findMaxPathSum(TreeNode root) { 42 | if (root.left == null && root.right == null) { 43 | maxPath = Math.max(maxPath, root.val); 44 | return root.val; 45 | } 46 | 47 | int leftPathSum = 0; 48 | int rightPathSum = 0; 49 | if (root.left != null) 50 | leftPathSum = Math.max(0, findMaxPathSum(root.left)); 51 | if (root.right != null) 52 | rightPathSum = Math.max(0, findMaxPathSum(root.right)); 53 | 54 | maxPath = Math.max(maxPath, root.val + leftPathSum + rightPathSum); 55 | return root.val + Math.max(leftPathSum, rightPathSum); 56 | } 57 | } 58 | ``` 59 | 60 | ## Complexity Analysis 61 | - **Time Complexity**: O(N), where N is the number of nodes in the binary tree. We visit each node once. 62 | - **Space Complexity**: O(H), where H is the height of the binary tree. The space is used for the recursive call stack. 63 | 64 | ## Code Explanation 65 | 1. We define a recursive function `findMaxPathSum` that calculates the maximum path sum passing through a given node. 66 | 2. At each node, we calculate the maximum path sum that includes the node itself and return it to the parent node. 67 | 3. We update the global maximum path sum (`maxPath`) whenever we encounter a new maximum during the traversal. 68 | 4. We handle the base case when a node has no left or right child (i.e., it is a leaf node). 69 | 5. We traverse the binary tree in a depth-first manner, starting from the root. 70 | 6. Finally, we return the maximum path sum found after traversing the entire tree. 71 | -------------------------------------------------------------------------------- /Blind 75/27. Binary Tree Level Order Traversal.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 102: [Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/) 3 | 4 | ## Problem Description 5 | 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). 6 | 7 | ## Solution Approach 8 | - We perform a level order traversal using a queue data structure. 9 | - We iterate through each level of the tree, adding the values of nodes at each level to the result list. 10 | 11 | ## Java Solution Code 12 | 13 | ```java 14 | /** 15 | * Definition for a binary tree node. 16 | * public class TreeNode { 17 | * int val; 18 | * TreeNode left; 19 | * TreeNode right; 20 | * TreeNode() {} 21 | * TreeNode(int val) { this.val = val; } 22 | * TreeNode(int val, TreeNode left, TreeNode right) { 23 | * this.val = val; 24 | * this.left = left; 25 | * this.right = right; 26 | * } 27 | * } 28 | */ 29 | class Solution { 30 | public List> levelOrder(TreeNode root) { 31 | List> levelOrder = new ArrayList<>(); 32 | 33 | if (root == null) 34 | return levelOrder; 35 | 36 | Queue queue = new LinkedList<>(); 37 | queue.offer(root); 38 | 39 | while (!queue.isEmpty()) { 40 | List level = new ArrayList<>(); 41 | int size = queue.size(); 42 | 43 | for (int i = 0; i < size; i++) { 44 | TreeNode current = queue.poll(); 45 | level.add(current.val); 46 | 47 | if (current.left != null) 48 | queue.offer(current.left); 49 | 50 | if (current.right != null) 51 | queue.offer(current.right); 52 | } 53 | levelOrder.add(level); 54 | } 55 | return levelOrder; 56 | } 57 | } 58 | ``` 59 | 60 | ## Complexity Analysis 61 | - **Time Complexity**: O(N), where N is the number of nodes in the binary tree. We visit each node once. 62 | - **Space Complexity**: O(N), for the queue data structure, which can hold up to N/2 nodes in the worst case, where N is the number of nodes in the binary tree. 63 | 64 | ## Code Explanation 65 | 1. We create a result list `levelOrder` to store the level order traversal of the binary tree. 66 | 2. We use a queue to perform level order traversal. We start by adding the root node to the queue. 67 | 3. We iterate through each level of the tree using a while loop until the queue is empty. 68 | 4. At each level, we create a list `level` to store the values of nodes at that level. 69 | 5. We iterate through the nodes at the current level, adding their values to the `level` list. 70 | 6. While traversing each node, if the node has left and right children, we add them to the queue for the next level traversal. 71 | 7. Once we finish traversing the current level, we add the `level` list to the `levelOrder` result list. 72 | 8. Finally, we return the `levelOrder` list containing the level order traversal of the binary tree. 73 | -------------------------------------------------------------------------------- /Blind 75/10. Search in Rotated Sorted Array.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 33: [Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/) 2 | 3 | ## Problem Description 4 | Given an integer array `nums` sorted in ascending order, which is rotated at some pivot point unknown beforehand, and a `target` value to search. If the target is found in the array, return its index. Otherwise, return -1. 5 | 6 | ## Solution Approach 7 | - We perform binary search on the rotated sorted array to find the target element. 8 | - We update the boundaries of the search based on whether the mid element is in the left or right half of the rotated array. 9 | 10 | ## Java Solution Code 11 | 12 | ```java 13 | class Solution { 14 | public int search(int[] nums, int target) { 15 | // Get the length of the array 16 | int n = nums.length; 17 | // Initialize pointers for binary search 18 | int low = 0, high = n - 1; 19 | 20 | // Binary search loop 21 | while (low <= high) { 22 | // Calculate the middle index 23 | int mid = low + (high - low) / 2; 24 | // If target found at mid index, return mid 25 | if (nums[mid] == target) 26 | return mid; 27 | // If left half is sorted 28 | else if (nums[low] <= nums[mid]) { 29 | // If target is in the right half or outside the sorted left half 30 | if (target > nums[mid] || target < nums[low]) 31 | low = mid + 1; // Move the low pointer to the right half 32 | else 33 | high = mid - 1; // Move the high pointer to the left half 34 | } 35 | // If right half is sorted 36 | else { 37 | // If target is in the left half or outside the sorted right half 38 | if (target < nums[mid] || target > nums[high]) 39 | high = mid - 1; // Move the high pointer to the left half 40 | else 41 | low = mid + 1; // Move the low pointer to the right half 42 | } 43 | } 44 | return -1; // Target not found 45 | } 46 | } 47 | ``` 48 | 49 | ## Complexity Analysis 50 | - **Time Complexity**: O(log N), where N is the number of elements in the array. 51 | - **Space Complexity**: O(1), constant extra space is used. 52 | 53 | ## Code Explanation 54 | 1. We initialize pointers `low` and `high` to the start and end of the array, respectively. 55 | 2. We use a binary search loop to iterate until `low` is less than or equal to `high`. 56 | 3. In each iteration, we calculate the `mid` index using the formula `low + (high - low) / 2`. 57 | 4. We check if the `target` is found at the `mid` index. If yes, we return `mid`. 58 | 5. If the left half is sorted (`nums[low] <= nums[mid]`), we determine if the `target` is in the right half or outside the sorted left half. We adjust the `low` or `high` pointers accordingly. 59 | 6. If the right half is sorted, we determine if the `target` is in the left half or outside the sorted right half. We adjust the `low` or `high` pointers accordingly. 60 | 7. If the `target` is not found in the array, we return `-1`. 61 | -------------------------------------------------------------------------------- /Blind 75/48. Word Search II.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 212: [Word Search II](https://leetcode.com/problems/word-search-ii/) 2 | 3 | ## Problem Description 4 | 5 | Given a 2D board and a list of words from the dictionary, find all words in the board. 6 | 7 | Each word must be constructed from letters of sequentially adjacent cells, where "adjacent" cells are horizontally or vertically neighboring. The same letter cell may not be used more than once in a word. 8 | 9 | ## Solution Approach 10 | 11 | We can solve this problem using a Trie data structure and DFS (Depth-First Search). We first build a Trie from the given list of words. Then, we perform a depth-first search (DFS) traversal on the board to find words that exist in the Trie. 12 | 13 | ## Java Solution 14 | 15 | ```java 16 | class Solution { 17 | public List findWords(char[][] board, String[] words) { 18 | List res = new ArrayList<>(); 19 | TrieNode root = buildTrie(words); 20 | for (int i = 0; i < board.length; i++) { 21 | for (int j = 0; j < board[0].length; j++) { 22 | dfs(board, i, j, root, res); 23 | } 24 | } 25 | return res; 26 | } 27 | 28 | public void dfs(char[][] board, int i, int j, TrieNode p, List res) { 29 | char c = board[i][j]; 30 | if (c == '#' || p.next[c - 'a'] == null) 31 | return; 32 | p = p.next[c - 'a']; 33 | if (p.word != null) { // found one 34 | res.add(p.word); 35 | p.word = null; // de-duplicate 36 | } 37 | 38 | board[i][j] = '#'; 39 | if (i > 0) 40 | dfs(board, i - 1, j, p, res); 41 | if (j > 0) 42 | dfs(board, i, j - 1, p, res); 43 | if (i < board.length - 1) 44 | dfs(board, i + 1, j, p, res); 45 | if (j < board[0].length - 1) 46 | dfs(board, i, j + 1, p, res); 47 | board[i][j] = c; 48 | } 49 | 50 | public TrieNode buildTrie(String[] words) { 51 | TrieNode root = new TrieNode(); 52 | for (String w : words) { 53 | TrieNode p = root; 54 | for (char c : w.toCharArray()) { 55 | int i = c - 'a'; 56 | if (p.next[i] == null) 57 | p.next[i] = new TrieNode(); 58 | p = p.next[i]; 59 | } 60 | p.word = w; 61 | } 62 | return root; 63 | } 64 | 65 | class TrieNode { 66 | TrieNode[] next = new TrieNode[26]; 67 | String word; 68 | } 69 | } 70 | ``` 71 | 72 | ## Complexity Analysis 73 | 74 | - **Time Complexity**: O(N*M), where N is the number of rows and M is the number of columns in the board. 75 | - **Space Complexity**: O(L), where L is the total number of characters in all words in the dictionary. 76 | 77 | ## Code Explanation 78 | 79 | - We start by building a Trie from the given list of words. 80 | - Then, we perform a depth-first search (DFS) traversal on the board. 81 | - During DFS traversal, we check if the current character exists in the Trie. If it does, we continue the traversal to find the word. 82 | - We use '#' to mark visited cells and avoid revisiting them in the DFS traversal. 83 | -------------------------------------------------------------------------------- /Blind 75/46. Implement Trie (Prefix Tree).md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 208: [Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/) 2 | 3 | ## Problem Description 4 | 5 | Implement a trie with insert, search, and startsWith methods. 6 | 7 | ## Solution Approach 8 | 9 | We implement a Trie data structure where each node contains an array of child nodes representing each character in the alphabet. We define methods to insert a word into the trie, search for a word in the trie, and check if a prefix exists in the trie. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | class Trie { 15 | Node root; 16 | 17 | public Trie() { 18 | root = new Node(); 19 | } 20 | 21 | public void insert(String word) { 22 | root.insert(word, 0); 23 | } 24 | 25 | public boolean search(String word) { 26 | return root.search(word, 0); 27 | } 28 | 29 | public boolean startsWith(String prefix) { 30 | return root.startsWith(prefix, 0); 31 | } 32 | 33 | class Node { 34 | Node[] nodes; 35 | boolean isEnd; 36 | 37 | Node() { 38 | nodes = new Node[26]; 39 | } 40 | 41 | private void insert(String word, int idx) { 42 | if (idx >= word.length()) return; 43 | int i = word.charAt(idx) - 'a'; 44 | if (nodes[i] == null) { 45 | nodes[i] = new Node(); 46 | } 47 | 48 | if (idx == word.length()-1) nodes[i].isEnd = true; 49 | nodes[i].insert(word, idx+1); 50 | } 51 | 52 | private boolean search(String word, int idx) { 53 | if (idx >= word.length()) return false; 54 | Node node = nodes[word.charAt(idx) - 'a']; 55 | if (node == null) return false; 56 | if (idx == word.length() - 1 && node.isEnd) return true; 57 | 58 | return node.search(word, idx+1); 59 | 60 | } 61 | 62 | private boolean startsWith(String prefix, int idx) { 63 | if (idx >= prefix.length()) return false; 64 | Node node = nodes[prefix.charAt(idx) - 'a']; 65 | if (node == null) return false; 66 | if (idx == prefix.length() - 1) return true; 67 | 68 | return node.startsWith(prefix, idx+1); 69 | } 70 | } 71 | } 72 | ``` 73 | 74 | ## Complexity Analysis 75 | 76 | - **Time Complexity**: 77 | - Insert: O(n), where n is the length of the word being inserted. 78 | - Search: O(n), where n is the length of the word being searched. 79 | - StartsWith: O(m), where m is the length of the prefix. 80 | - **Space Complexity**: O(m*n), where m is the number of words and n is the average length of the words. 81 | 82 | ## Code Explanation 83 | 84 | - We define a Trie class with methods to insert, search, and check if a prefix exists. 85 | - Each node in the trie contains an array of child nodes representing each character in the alphabet. 86 | - We recursively insert each character of the word into the trie starting from the root node. 87 | - We recursively search for each character of the word in the trie starting from the root node. 88 | - We recursively check if each character of the prefix exists in the trie starting from the root node. 89 | -------------------------------------------------------------------------------- /Blind 75/29. Construct Binary Tree from Preorder and Inorder Traversal.md: -------------------------------------------------------------------------------- 1 | 2 | # LeetCode Problem 105: [Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/) 3 | 4 | ## Problem Description 5 | Given two integer arrays `preorder` and `inorder` where `preorder` is the preorder traversal of a binary tree and `inorder` is the inorder traversal of the same tree, construct and return the binary tree. 6 | 7 | ## Solution Approach 8 | - We recursively build the binary tree using the preorder and inorder traversal arrays. 9 | - We use the first element of the preorder array as the root of the current subtree. 10 | - We find the index of the root element in the inorder array to determine the left and right subtrees. 11 | - We recursively build the left and right subtrees based on the indexes obtained from the inorder traversal. 12 | 13 | ## Java Solution Code 14 | 15 | ```java 16 | /** 17 | * Definition for a binary tree node. 18 | * public class TreeNode { 19 | * int val; 20 | * TreeNode left; 21 | * TreeNode right; 22 | * TreeNode() {} 23 | * TreeNode(int val) { this.val = val; } 24 | * TreeNode(int val, TreeNode left, TreeNode right) { 25 | * this.val = val; 26 | * this.left = left; 27 | * this.right = right; 28 | * } 29 | * } 30 | */ 31 | class Solution { 32 | public TreeNode buildTree(int[] preorder, int[] inorder) { 33 | return buildBinaryTree(0, 0, inorder.length - 1, preorder, inorder); 34 | } 35 | 36 | public TreeNode buildBinaryTree(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder) { 37 | if (preStart > preorder.length - 1 || inStart > inEnd) { 38 | return null; 39 | } 40 | 41 | TreeNode root = new TreeNode(preorder[preStart]); 42 | int inIndex = 0; 43 | 44 | for (int i = inStart; i <= inEnd; i++) { 45 | if (inorder[i] == root.val) { 46 | inIndex = i; 47 | } 48 | } 49 | 50 | root.left = buildBinaryTree(preStart + 1, inStart, inIndex - 1, preorder, inorder); 51 | root.right = buildBinaryTree(preStart + inIndex - inStart + 1, inIndex + 1, inEnd, preorder, inorder); 52 | 53 | return root; 54 | } 55 | } 56 | ``` 57 | 58 | ## Complexity Analysis 59 | - **Time Complexity**: O(N), where N is the number of nodes in the binary tree. We visit each node exactly once during the construction process. 60 | - **Space Complexity**: O(N), where N is the number of nodes in the binary tree. This space is used for the recursive call stack during the construction process. 61 | 62 | ## Code Explanation 63 | 1. The `buildTree` function takes the preorder and inorder traversal arrays as input and returns the root of the constructed binary tree. 64 | 2. In the `buildBinaryTree` helper function, we recursively build the binary tree using the preorder and inorder traversal arrays along with the start and end indexes. 65 | 3. We use the first element of the preorder array as the root of the current subtree. 66 | 4. We find the index of the root element in the inorder array to determine the left and right subtrees. 67 | 5. We recursively build the left and right subtrees based on the indexes obtained from the inorder traversal. 68 | 6. Finally, we return the root of the constructed binary tree. 69 | -------------------------------------------------------------------------------- /Blind 75/70. Pacific Atlantic Water Flow.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 417: [Pacific Atlantic Water Flow](https://leetcode.com/problems/pacific-atlantic-water-flow/) 2 | 3 | ## Problem Description 4 | 5 | Given an `m x n` matrix of non-negative integers representing the height of each unit cell in a continent, the "Pacific ocean" touches the left and top edges of the matrix, and the "Atlantic ocean" touches the right and bottom edges. 6 | 7 | Water can only flow in four directions (up, down, left, or right) from a cell to another one with height equal or lower. 8 | 9 | Find the list of grid coordinates where water can flow to both the Pacific and Atlantic oceans. 10 | 11 | ## Solution Approach 12 | 13 | We perform depth-first search (DFS) from the cells on the borders of the matrix, marking cells that can reach the Pacific and Atlantic oceans separately. Then, we find the cells that can reach both oceans and return their coordinates. 14 | 15 | ## Java Solution 16 | 17 | ```java 18 | class Solution { 19 | public List> pacificAtlantic(int[][] heights) { 20 | List> result = new ArrayList<>(); 21 | int n = heights.length, m = heights[0].length; 22 | boolean[][] pacificVisited = new boolean[n][m]; 23 | boolean[][] atlanticVisited = new boolean[n][m]; 24 | 25 | for (int i = 0; i < n; i++) { 26 | dfs(i, 0, heights, pacificVisited, Integer.MIN_VALUE); 27 | dfs(i, m - 1, heights, atlanticVisited, Integer.MIN_VALUE); 28 | } 29 | 30 | for (int j = 0; j < m; j++) { 31 | dfs(0, j, heights, pacificVisited, Integer.MIN_VALUE); 32 | dfs(n - 1, j, heights, atlanticVisited, Integer.MIN_VALUE); 33 | } 34 | 35 | for (int i = 0; i < n; i++) { 36 | for (int j = 0; j < m; j++) { 37 | if (pacificVisited[i][j] && atlanticVisited[i][j]) { 38 | ArrayList cell = new ArrayList<>(); 39 | cell.add(i); 40 | cell.add(j); 41 | result.add(cell); 42 | } 43 | } 44 | } 45 | return result; 46 | } 47 | 48 | void dfs(int row, int col, int[][] heights, boolean[][] visited, int prevHeight) { 49 | if (row < 0 || col < 0 || row == heights.length || col == heights[0].length || visited[row][col] || heights[row][col] < prevHeight) 50 | return; 51 | 52 | visited[row][col] = true; 53 | 54 | dfs(row - 1, col, heights, visited, heights[row][col]); 55 | dfs(row + 1, col, heights, visited, heights[row][col]); 56 | dfs(row, col - 1, heights, visited, heights[row][col]); 57 | dfs(row, col + 1, heights, visited, heights[row][col]); 58 | } 59 | } 60 | ``` 61 | 62 | ## Complexity Analysis 63 | 64 | - **Time Complexity**: O(n * m), where n is the number of rows and m is the number of columns in the matrix. We traverse the entire matrix once. 65 | - **Space Complexity**: O(n * m), where n is the number of rows and m is the number of columns in the matrix. We use boolean arrays to mark visited cells. 66 | 67 | ## Code Explanation 68 | 69 | - We perform depth-first search (DFS) from the cells on the borders of the matrix, marking cells that can reach the Pacific and Atlantic oceans separately. 70 | - Then, we find the cells that can reach both oceans and return their coordinates. 71 | -------------------------------------------------------------------------------- /Blind 75/63. Serialize and Deserialize Binary Tree.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 62: [Serialize and Deserialize Binary Tree](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/) 2 | 3 | ## Problem Description 4 | 5 | Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. 6 | 7 | Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure. 8 | 9 | ## Solution Approach 10 | 11 | The problem can be solved using a preorder traversal for serialization and deserialization. We traverse the tree in a preorder manner and append each node's value to the string, marking null nodes with a special character. For deserialization, we split the string by the delimiter and use a queue to reconstruct the binary tree. 12 | 13 | ## Java Solution 14 | 15 | ```java 16 | import java.util.Arrays; 17 | import java.util.Deque; 18 | import java.util.LinkedList; 19 | 20 | public class Codec { 21 | // Encodes a tree to a single string. 22 | public String serialize(TreeNode root) { 23 | StringBuilder res = new StringBuilder(); 24 | BuildString(root, res); 25 | return res.toString(); 26 | } 27 | 28 | void BuildString(TreeNode root, StringBuilder res) { 29 | if (root == null) { 30 | res.append("X").append(","); 31 | } else { 32 | res.append(root.val).append(","); 33 | BuildString(root.left, res); 34 | BuildString(root.right, res); 35 | } 36 | } 37 | 38 | // Decodes your encoded data to tree. 39 | public TreeNode deserialize(String data) { 40 | Deque nodes = new LinkedList<>(); 41 | nodes.addAll(Arrays.asList(data.split(","))); 42 | 43 | return BuildTree(nodes); 44 | } 45 | 46 | TreeNode BuildTree(Deque nodes) { 47 | String val = nodes.remove(); 48 | if (val.equals("X")) 49 | return null; 50 | 51 | TreeNode node = new TreeNode(Integer.valueOf(val)); 52 | node.left = BuildTree(nodes); 53 | node.right = BuildTree(nodes); 54 | 55 | return node; 56 | } 57 | } 58 | ``` 59 | 60 | ## Complexity Analysis 61 | 62 | The time complexity for both serialization and deserialization is O(N), where N is the number of nodes in the binary tree. 63 | 64 | The space complexity for both serialization and deserialization is O(N), where N is the number of nodes in the binary tree. 65 | 66 | ## Code Explanation 67 | 68 | - The `serialize` method performs a preorder traversal of the binary tree and constructs a string representation of the tree. 69 | - The `deserialize` method reconstructs the binary tree from the string by using a queue and performing a preorder traversal. 70 | 71 | To use this Codec class, you can instantiate an object and call the `serialize` method to serialize a binary tree, and then call the `deserialize` method to deserialize the string back into a binary tree. Make sure to replace `root` with the root of the binary tree you want to serialize or deserialize. 72 | -------------------------------------------------------------------------------- /Blind 75/60. Alien Dictionary.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 60: [Alien Dictionary](https://leetcode.com/problems/alien-dictionary/) 2 | 3 | ## Problem Description 4 | 5 | There is a new alien language that uses the English alphabet. However, the order among letters are unknown to you. You are given a list of strings `words` representing the dictionary where `words[i]` is the ith word in the dictionary. You need to determine the order of letters in this language. 6 | 7 | ## Solution Approach 8 | 9 | To determine the order of letters in the alien language, we can construct a directed graph where each node represents a letter, and each directed edge `(u, v)` indicates that letter `u` comes before letter `v` in the alien language. Then, we perform a topological sort on this graph to obtain the order of letters. 10 | 11 | ## Java Solution 12 | 13 | ```java 14 | import java.util.*; 15 | 16 | class Solution { 17 | public String alienOrder(String[] words) { 18 | Map> graph = new HashMap<>(); 19 | int[] inDegree = new int[26]; 20 | 21 | buildGraph(words, graph, inDegree); 22 | 23 | StringBuilder sb = new StringBuilder(); 24 | Queue queue = new LinkedList<>(); 25 | 26 | for (char c : graph.keySet()) { 27 | if (inDegree[c - 'a'] == 0) { 28 | queue.offer(c); 29 | sb.append(c); 30 | } 31 | } 32 | 33 | while (!queue.isEmpty()) { 34 | char current = queue.poll(); 35 | if (!graph.containsKey(current)) continue; 36 | for (char neighbor : graph.get(current)) { 37 | inDegree[neighbor - 'a']--; 38 | if (inDegree[neighbor - 'a'] == 0) { 39 | queue.offer(neighbor); 40 | sb.append(neighbor); 41 | } 42 | } 43 | } 44 | 45 | return sb.length() == graph.size() ? sb.toString() : ""; 46 | } 47 | 48 | private void buildGraph(String[] words, Map> graph, int[] inDegree) { 49 | for (String word : words) { 50 | for (char c : word.toCharArray()) { 51 | graph.putIfAbsent(c, new HashSet<>()); 52 | } 53 | } 54 | 55 | for (int i = 0; i < words.length - 1; i++) { 56 | String word1 = words[i]; 57 | String word2 = words[i + 1]; 58 | int minLength = Math.min(word1.length(), word2.length()); 59 | 60 | for (int j = 0; j < minLength; j++) { 61 | char parent = word1.charAt(j); 62 | char child = word2.charAt(j); 63 | if (parent != child) { 64 | if (!graph.get(parent).contains(child)) { 65 | graph.get(parent).add(child); 66 | inDegree[child - 'a']++; 67 | } 68 | break; 69 | } 70 | } 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | ## Complexity Analysis 77 | 78 | - **Time Complexity**: O(N + E), where N is the total number of characters in the dictionary and E is the total number of unique character pairs in adjacent words. 79 | - **Space Complexity**: O(N + E), where N is the total number of characters in the dictionary and E is the total number of unique character pairs in adjacent words. 80 | 81 | ## Code Explanation 82 | 83 | - We build a directed graph and calculate in-degrees for each character based on the given words. 84 | - We perform topological sorting using a queue to determine the order of letters in the alien language. 85 | - The resulting order is returned as a string. 86 | -------------------------------------------------------------------------------- /Blind 75/33. Longest Consecutive Sequence.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 128: [Longest Consecutive Sequence](https://leetcode.com/problems/longest-consecutive-sequence/) 2 | 3 | ## Problem Description 4 | 5 | Given an unsorted array of integers `nums`, return the length of the longest consecutive elements sequence. 6 | 7 | A sequence follows the pattern: `... -> n-2 -> n-1 -> n` where n is the current element. 8 | 9 | ## Solution Approaches 10 | 11 | ### Approach 1: Union-Find 12 | 13 | ```java 14 | import java.util.HashMap; 15 | 16 | class Solution { 17 | public int longestConsecutive(int[] nums) { 18 | int n = nums.length; 19 | 20 | if (n <= 1) 21 | return n; 22 | 23 | UnionFind uf = new UnionFind(n); 24 | HashMap numIndexMap = new HashMap<>(); 25 | 26 | for (int i = 0; i < n; i++) { 27 | int currentNum = nums[i]; 28 | if (numIndexMap.containsKey(currentNum)) 29 | continue; 30 | 31 | numIndexMap.put(currentNum, i); 32 | 33 | if (numIndexMap.containsKey(currentNum - 1)) 34 | uf.unionByRank(i, numIndexMap.get(currentNum - 1)); 35 | 36 | if (numIndexMap.containsKey(currentNum + 1)) 37 | uf.unionByRank(i, numIndexMap.get(currentNum + 1)); 38 | } 39 | 40 | return uf.findMax(); 41 | } 42 | } 43 | 44 | class UnionFind { 45 | int[] parent; 46 | int[] rank; 47 | 48 | UnionFind(int n) { 49 | parent = new int[n]; 50 | rank = new int[n]; 51 | 52 | for (int i = 0; i < n; i++) { 53 | parent[i] = i; 54 | rank[i] = 1; 55 | } 56 | } 57 | 58 | public void unionByRank(int u, int v) { 59 | int parentU = findParent(u); 60 | int parentV = findParent(v); 61 | 62 | if (parentU == parentV) 63 | return; 64 | if (rank[parentU] < rank[parentV]) 65 | parent[parentU] = parentV; 66 | else if (rank[parentU] > rank[parentV]) 67 | parent[parentV] = parentU; 68 | else { 69 | parent[parentU] = parentV; 70 | rank[v]++; 71 | } 72 | } 73 | 74 | public int findParent(int u) { 75 | if (parent[u] == u) 76 | return u; 77 | 78 | return parent[u] = findParent(parent[u]); 79 | } 80 | 81 | public int findMax() { 82 | int maxCount = 0; 83 | int[] count = new int[rank.length]; 84 | 85 | for (int i = 0; i < count.length; i++) { 86 | int root = findParent(i); 87 | count[root]++; 88 | maxCount = Math.max(maxCount, count[root]); 89 | } 90 | 91 | return maxCount; 92 | } 93 | } 94 | 95 | ``` 96 | 97 | ### Approach 2: HashSet 98 | 99 | ```java 100 | import java.util.HashSet; 101 | import java.util.Set; 102 | 103 | class Solution { 104 | public int longestConsecutive(int[] nums) { 105 | Set s = new HashSet<>(); 106 | for(int i=0;i targetMap = new HashMap<>(); 23 | Map windowMap = new HashMap<>(); 24 | int targetLength = t.length(); 25 | int sLength = s.length(); 26 | 27 | // Constructing the targetMap to count characters in string t 28 | for (int i = 0; i < targetLength; i++) { 29 | char ch = t.charAt(i); 30 | targetMap.put(ch, targetMap.getOrDefault(ch, 0) + 1); 31 | } 32 | 33 | int requiredChars = targetMap.size(); 34 | int left = 0, right = 0; 35 | int currentChars = 0; 36 | int minLength = Integer.MAX_VALUE; 37 | int start = 0, end = 0; 38 | 39 | while (right < sLength) { 40 | // Expand the window by adding the right character 41 | char rightChar = s.charAt(right); 42 | windowMap.put(rightChar, windowMap.getOrDefault(rightChar, 0) + 1); 43 | 44 | // Check if the added character contributes to the required characters 45 | if (targetMap.containsKey(rightChar) && windowMap.get(rightChar).equals(targetMap.get(rightChar))) { 46 | currentChars++; 47 | } 48 | 49 | // Contract the window 50 | while (currentChars == requiredChars) { 51 | // Update the minimum length and record the start and end indices 52 | if (right - left + 1 < minLength) { 53 | minLength = right - left + 1; 54 | start = left; 55 | end = right; 56 | } 57 | 58 | // Move the left pointer to contract the window 59 | char leftChar = s.charAt(left); 60 | windowMap.put(leftChar, windowMap.get(leftChar) - 1); 61 | 62 | // Check if the removed character affects the required characters 63 | if (targetMap.containsKey(leftChar) && windowMap.get(leftChar) < targetMap.get(leftChar)) { 64 | currentChars--; 65 | } 66 | 67 | left++; // Move the left pointer to the right 68 | } 69 | 70 | right++; // Move the right pointer to the right 71 | } 72 | 73 | return minLength == Integer.MAX_VALUE ? "" : s.substring(start, end + 1); 74 | } 75 | } 76 | ``` 77 | 78 | ## Complexity Analysis 79 | - **Time Complexity**: O(S + T), where S is the length of string `s` and T is the length of string `t`. 80 | - **Space Complexity**: O(S + T), where S is the length of string `s` and T is the length of string `t`. 81 | 82 | ## Code Explanation 83 | 1. We construct a map `targetMap` to count the frequency of characters in the target string `t`. 84 | 2. We use a sliding window approach with two pointers `left` and `right` to find the minimum window substring. 85 | 3. As we expand the window, we update the windowMap to count the frequency of characters in the current window. 86 | 4. We contract the window when all characters in the target string are present in the window. 87 | 5. At each step, we update the minimum length and record the start and end indices of the minimum window substring. 88 | 89 | Detailed Code Explanation: 90 | - We first create two maps, `targetMap` and `windowMap`, to store the character frequencies of the target string `t` and the current window, respectively. 91 | - We iterate through the characters of string `t` and populate `targetMap` with the character frequencies. 92 | - We use two pointers, `left` and `right`, to define the window boundaries. Initially, both pointers are set to the beginning of the string `s`. 93 | - We iterate through the string `s` using the `right` pointer and expand the window by adding characters to `windowMap`. 94 | - As we expand the window, we check if the added character contributes to the required characters in `t`. If it does, we increment the `currentChars` count. 95 | - When the window contains all required characters, we start contracting the window by moving the `left` pointer. 96 | - We update the minimum length and record the start and end indices of the minimum window substring whenever we find a valid window. 97 | - Finally, we return the minimum window substring or an empty string if no valid window is found. 98 | -------------------------------------------------------------------------------- /Blind 75/43. Number of Islands.md: -------------------------------------------------------------------------------- 1 | # LeetCode Problem 200: [Number of Islands](https://leetcode.com/problems/number-of-islands/) 2 | 3 | ## Problem Description 4 | 5 | Given a 2D grid `grid` of `'1'`s (land) and `'0'`s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. Assume all four edges of the grid are all surrounded by water. 6 | 7 | ## Solution Approaches 8 | 9 | ### DFS Approach 10 | 11 | - We use Depth First Search (DFS) to traverse the grid. 12 | - Whenever we encounter a land cell `'1'` that hasn't been visited, we increment the count of islands and recursively mark all adjacent land cells as visited. 13 | - This approach effectively explores each island and counts it. 14 | 15 | ### BFS Approach 16 | 17 | - We use Breadth First Search (BFS) to traverse the grid. 18 | - We start BFS from each unvisited land cell `'1'` and mark all reachable land cells as visited while exploring. 19 | - Each BFS traversal discovers one island. 20 | 21 | ### Union Find Approach 22 | 23 | - We use Union Find data structure to solve this problem. 24 | - We iterate through the grid and for each land cell `'1'`, we union it with its adjacent land cells. 25 | - Finally, we count the number of distinct connected components, which corresponds to the number of islands. 26 | 27 | ## Java Solutions 28 | 29 | ### DFS Solution 30 | 31 | ```java 32 | class Solution { 33 | // DFS method and helper functions 34 | public int numIslands(char[][] grid) { 35 | int count = 0; 36 | int n = grid.length, m = grid[0].length; 37 | boolean[][] visited = new boolean[n][m]; 38 | 39 | for (int i = 0; i < n; i++) { 40 | for (int j = 0; j < m; j++) { 41 | if (!visited[i][j] && grid[i][j] == '1') { 42 | dfs(i, j, grid, visited); 43 | count++; 44 | } 45 | } 46 | } 47 | return count; 48 | } 49 | 50 | void dfs(int i, int j, char[][] grid, boolean[][] visited) { 51 | if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] == '0' || visited[i][j]) 52 | return; 53 | 54 | visited[i][j] = true; 55 | dfs(i + 1, j, grid, visited); 56 | dfs(i - 1, j, grid, visited); 57 | dfs(i, j + 1, grid, visited); 58 | dfs(i, j - 1, grid, visited); 59 | } 60 | } 61 | ``` 62 | 63 | ### BFS Solution 64 | 65 | ```java 66 | class Solution { 67 | class Pair { 68 | int first; 69 | int second; 70 | 71 | public Pair(int first, int second) { 72 | this.first = first; 73 | this.second = second; 74 | } 75 | } 76 | 77 | public int numIslands(char[][] grid) { 78 | int count = 0; 79 | int n = grid.length, m = grid[0].length; 80 | boolean[][] visited = new boolean[n][m]; 81 | 82 | for (int i = 0; i < n; i++) { 83 | for (int j = 0; j < m; j++) { 84 | if (!visited[i][j] && grid[i][j] == '1') { 85 | bfs(i, j, grid, visited); 86 | count++; 87 | } 88 | } 89 | } 90 | return count; 91 | } 92 | 93 | void bfs(int i, int j, char[][] grid, boolean[][] visited) { 94 | Queue q = new LinkedList<>(); 95 | q.add(new Pair(i, j)); 96 | visited[i][j] = true; 97 | int n = grid.length, m = grid[0].length; 98 | 99 | while (!q.isEmpty()) { 100 | int row = q.peek().first; 101 | int col = q.peek().second; 102 | q.poll(); 103 | 104 | int[][] directions = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } }; 105 | 106 | for (int[] dir : directions) { 107 | int nRow = row + dir[0]; 108 | int nCol = col + dir[1]; 109 | 110 | if (nRow >= 0 && nCol >= 0 && nRow < n && nCol < m && !visited[nRow][nCol] && grid[nRow][nCol] == '1') { 111 | visited[nRow][nCol] = true; 112 | q.add(new Pair(nRow, nCol)); 113 | } 114 | } 115 | } 116 | } 117 | } 118 | ``` 119 | 120 | ### Union Find Solution 121 | 122 | ```java 123 | class Solution { 124 | public int numIslands(char[][] grid) { 125 | int n = grid.length , m = grid[0].length ; 126 | UnionFind uf = new UnionFind(n*m); 127 | 128 | for(int i=0;i 0 && grid[i - 1][j] == '1') 132 | uf.unionByRank(i * m + j, (i - 1) * m + j); 133 | 134 | if(j > 0 && grid[i][j - 1] == '1') 135 | uf.unionByRank(i * m + j, i * m + (j - 1)); 136 | 137 | } 138 | } 139 | } 140 | 141 | HashSet hs = new HashSet<>(); 142 | for(int i=0;i