diff --git a/README.md b/README.md index 23ffd54..409cca5 100644 --- a/README.md +++ b/README.md @@ -7,19 +7,20 @@ This repository contains awesome LeetCode resources to learn Data Structures and Algorithms (DSA) and prepare for Coding interviews. -If you want to practice curated list of LeetCode problems organized by patterns, checkout [AlgoMaster.io](https://algomaster.io) +👉 If you want to master DSA patterns, checkout [AlgoMaster.io](https://algomaster.io) ## 💡 Tips -- [How to Start LeetCode](https://www.youtube.com/watch?v=Nx4bvwU0DqE) - [How I Mastered DSA](https://blog.algomaster.io/p/how-i-mastered-data-structures-and-algorithms) +- [How to Start LeetCode](https://blog.algomaster.io/p/how-to-start-leetcode-in-2025) +- [15 Leetcode Patterns](https://blog.algomaster.io/p/15-leetcode-patterns) ## 📌 Fundamental Concepts - [Algorithmic Complexity](https://blog.algomaster.io/p/57bd4963-462f-4294-a972-4012691fc729) - [Big-O Cheat Sheet](https://www.bigocheatsheet.com/) +- [Arrays](https://www.youtube.com/watch?v=SlNq09scdWE&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) - [Bit Manipulation Techniques](https://blog.algomaster.io/p/c650df76-f978-46ee-a572-eb13c354905d) - [Sorting Algorithms](https://medium.com/jl-codes/understanding-sorting-algorithms-af6222995c8) -- [Linked List](https://leetcode.com/discuss/study-guide/1800120/become-master-in-linked-list) - - [Dummy Node Technique](https://blog.algomaster.io/p/5d7a1368-7a0c-461a-93a9-732333ceb2a8) +- [Linked List](https://www.youtube.com/watch?v=FbHf0ii0WDg&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) - [Queues](https://medium.com/basecs/to-queue-or-not-to-queue-2653bcde5b04) - [Stacks](https://medium.com/basecs/stacks-and-overflows-dbcf7854dc67) - [Hash Tables](https://medium.com/basecs/taking-hash-tables-off-the-shelf-139cbf4752f0) @@ -31,8 +32,8 @@ If you want to practice curated list of LeetCode problems organized by patterns, - [Binary Search](https://leetcode.com/discuss/study-guide/786126/Python-Powerful-Ultimate-Binary-Search-Template.-Solved-many-problems) - [Greedy Algorithm](https://www.freecodecamp.org/news/greedy-algorithms/) - [Dynamic Programming](https://medium.com/basecs/less-repetition-more-dynamic-programming-43d29830a630) -- [Graph Theory](https://medium.com/basecs/a-gentle-introduction-to-graph-theory-77969829ead8) -- [Important Graph Algorithms](https://blog.algomaster.io/p/master-graph-algorithms-for-coding) +- [Graph Theory](https://www.youtube.com/watch?v=xN5VGzK9_FQ&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Master Graph Algorithms](https://blog.algomaster.io/p/master-graph-algorithms-for-coding) - [DFS Traversal](https://medium.com/basecs/deep-dive-through-a-graph-dfs-traversal-8177df5d0f13) - [BFS Traversal](https://medium.com/basecs/going-broad-in-a-graph-bfs-traversal-959bd1a09255) - [Union-Find](https://leetcode.com/discuss/general-discussion/1072418/Disjoint-Set-Union-(DSU)Union-Find-A-Complete-Guide) @@ -42,14 +43,14 @@ If you want to practice curated list of LeetCode problems organized by patterns, ## 🚀 Patterns - [15 Leetcode Patterns](https://blog.algomaster.io/p/15-leetcode-patterns) - [20 DP Patterns](https://blog.algomaster.io/p/20-patterns-to-master-dynamic-programming) -- [Prefix Sum Pattern](https://www.youtube.com/watch?v=yuws7YK0Yng) -- [Top 'K' Elements Pattern](https://www.youtube.com/watch?v=6_v6OoxvMOE) -- [Fast and Slow Pointers Pattern](https://www.youtube.com/watch?v=b139yf7Ik-E) -- [Kadane's Algorithm](https://www.youtube.com/watch?v=NUWAXbSlsws) -- [Two Pointers Pattern](https://blog.algomaster.io/p/69025a2e-b0d5-4705-8507-bba16c2691f1) -- [Linked List In-place Reversal Pattern](https://www.youtube.com/watch?v=auoTGovuo9A) -- [Sliding Window Pattern](https://blog.algomaster.io/p/f4412a17-7a3a-4d0b-8e39-9ea8f429bf7c) -- [Monotonic Stack Pattern](https://blog.algomaster.io/p/5dabff21-11f4-470d-8e38-76ff07c63fdf) +- [Two Pointers Pattern](https://www.youtube.com/watch?v=QzZ7nmouLTI&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Sliding Window Pattern](https://www.youtube.com/watch?v=y2d0VHdvfdc&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Prefix Sum Pattern](https://www.youtube.com/watch?v=yuws7YK0Yng&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Fast and Slow Pointers Pattern](https://www.youtube.com/watch?v=b139yf7Ik-E&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Top 'K' Elements Pattern](https://www.youtube.com/watch?v=6_v6OoxvMOE&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Kadane's Algorithm](https://www.youtube.com/watch?v=NUWAXbSlsws&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Linked List In-place Reversal Pattern](https://www.youtube.com/watch?v=auoTGovuo9A&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) +- [Monotonic Stack Pattern](https://www.youtube.com/watch?v=DtJVwbbicjQ&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2) - [Overlapping Intervals Pattern](https://blog.algomaster.io/p/812e72f7-eced-4256-a4c1-00606ae50679) - [Backtracking Pattern](https://blog.algomaster.io/p/81d42ca2-600c-4252-aa33-a56462090048) - [Modified Binary Search Pattern](https://blog.algomaster.io/p/d0d81b04-4c2a-4b45-a101-5137c3146686) @@ -80,6 +81,7 @@ If you want to practice curated list of LeetCode problems organized by patterns, - [Leetcode Top Interview 150](https://leetcode.com/studyplan/top-interview-150/) ## 📺 YouTube Playlist +- [AlgoMaster DSA Playlist](https://www.youtube.com/playlist?list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2&pp=gAQB) - [AlgoMaster LeetCode Pattern Playlist](https://www.youtube.com/playlist?list=PLK63NuByH5o-tqaMUHRA4r8ObRW7PWz45) - [Abdul Bari's Algorithms Playlist](https://www.youtube.com/playlist?list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O) - [William Fiset's Data Structure Playlist](https://www.youtube.com/playlist?list=PLDV1Zeh2NRsB6SWUrDFW2RmDotAfPbeHu) @@ -109,3 +111,9 @@ If you want to practice curated list of LeetCode problems organized by patterns, - [LeetCode VS Code Extension](https://marketplace.visualstudio.com/items?itemName=LeetCode.vscode-leetcode): Solve LeetCode problems in VS Code. Your contributions are most welcome! + +--- + +

+ If you find this resource helpful, please give it a star ⭐️ and share it with others! +

diff --git a/patterns/c#/MonotonicStack.cs b/patterns/c#/MonotonicStack.cs new file mode 100644 index 0000000..2d1d89e --- /dev/null +++ b/patterns/c#/MonotonicStack.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; + +public class MonotonicStack { + public int[] NextGreaterElement(int[] nums) { + int n = nums.Length; + int[] result = new int[n]; + Array.Fill(result, -1); // Default to -1 if no greater element exists + Stack stack = new Stack(); // Stack stores indices + + for (int i = 0; i < n; i++) { + while (stack.Count > 0 && nums[i] > nums[stack.Peek()]) { + int index = stack.Pop(); + result[index] = nums[i]; + } + stack.Push(i); + } + return result; + } + + public int[] DailyTemperatures(int[] temperatures) { + int n = temperatures.Length; + int[] result = new int[n]; // Result array initialized with 0s + Stack stack = new Stack(); // Monotonic decreasing stack + + for (int i = 0; i < n; i++) { + while (stack.Count > 0 && temperatures[i] > temperatures[stack.Peek()]) { + int prevIndex = stack.Pop(); + result[prevIndex] = i - prevIndex; + } + stack.Push(i); + } + return result; + } +} \ No newline at end of file diff --git a/patterns/c#/SlidingWindow.cs b/patterns/c#/SlidingWindow.cs new file mode 100644 index 0000000..78fe833 --- /dev/null +++ b/patterns/c#/SlidingWindow.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; + +public class SlidingWindow { + public double FindMaxAverageBruteForce(int[] nums, int k) { + int n = nums.Length; + double maxAvg = double.MinValue; + + for (int i = 0; i <= n - k; i++) { + int sum = 0; + for (int j = i; j < i + k; j++) { + sum += nums[j]; + } + maxAvg = Math.Max(maxAvg, (double)sum / k); + } + return maxAvg; + } + + public double FindMaxAverageSlidingWindow(int[] nums, int k) { + int n = nums.Length; + int sum = 0; + + for (int i = 0; i < k; i++) { + sum += nums[i]; + } + + int maxSum = sum; + + for (int i = k; i < n; i++) { + sum += nums[i]; + sum -= nums[i - k]; + maxSum = Math.Max(maxSum, sum); + } + + return (double)maxSum / k; + } + + public int LengthOfLongestSubstringSlidingWindow(string s) { + HashSet seen = new HashSet(); + int maxLength = 0, left = 0; + + for (int right = 0; right < s.Length; right++) { + while (seen.Contains(s[right])) { + seen.Remove(s[left]); + left++; + } + seen.Add(s[right]); + maxLength = Math.Max(maxLength, right - left + 1); + } + return maxLength; + } + + public int LengthOfLongestSubstringSlidingWindowFrequencyArray(string s) { + int[] freq = new int[128]; + int maxLength = 0, left = 0; + + for (int right = 0; right < s.Length; right++) { + freq[s[right]]++; + + while (freq[s[right]] > 1) { + freq[s[left]]--; + left++; + } + + maxLength = Math.Max(maxLength, right - left + 1); + } + return maxLength; + } +} \ No newline at end of file diff --git a/patterns/c#/TwoPointers.cs b/patterns/c#/TwoPointers.cs new file mode 100644 index 0000000..086b691 --- /dev/null +++ b/patterns/c#/TwoPointers.cs @@ -0,0 +1,59 @@ +using System; + +public class TwoPointers { + // Move Zeroes using Two Pointers + public void MoveZeroesTwoPointers(int[] nums) { + int left = 0; // Pointer for placing non-zero elements + + // Iterate with right pointer + for (int right = 0; right < nums.Length; right++) { + if (nums[right] != 0) { + // Swap elements if right pointer finds a non-zero + (nums[left], nums[right]) = (nums[right], nums[left]); + left++; // Move left pointer forward + } + } + } + + // Brute Force approach for Container with Most Water + public int MaxAreaBruteForce(int[] height) { + int n = height.Length; + int maxArea = 0; + + // Check all pairs (i, j) + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + // Compute the minimum height and width + int minHeight = Math.Min(height[i], height[j]); + int width = j - i; + int area = minHeight * width; // Compute water contained + + maxArea = Math.Max(maxArea, area); // Update max water + } + } + return maxArea; + } + + // Two Pointers approach for Container with Most Water + public int MaxAreaTwoPointers(int[] height) { + int left = 0, right = height.Length - 1; + int maxArea = 0; + + // Move pointers toward each other + while (left < right) { + int width = right - left; // Distance between lines + int minHeight = Math.Min(height[left], height[right]); // Compute height + int area = minHeight * width; // Compute water contained + + maxArea = Math.Max(maxArea, area); // Update max water + + // Move the pointer pointing to the shorter height + if (height[left] < height[right]) { + left++; // Move left pointer forward + } else { + right--; // Move right pointer backward + } + } + return maxArea; + } +} \ No newline at end of file diff --git a/patterns/c++/KadaneAlgorithm.cpp b/patterns/c++/KadaneAlgorithm.cpp index e69de29..609f6ed 100644 --- a/patterns/c++/KadaneAlgorithm.cpp +++ b/patterns/c++/KadaneAlgorithm.cpp @@ -0,0 +1,19 @@ +#include +#include // For std::max + +class KadaneAlgorithm { +public: + int maxSubArray(std::vector& nums) { + int currentSum = nums[0]; // Start with the first element + int maxSum = nums[0]; // Initialize maxSum with the first element + + // Traverse the array from the second element + for (size_t i = 1; i < nums.size(); i++) { + // If currentSum is negative, reset to current element + currentSum = std::max(nums[i], currentSum + nums[i]); + // Update maxSum if currentSum is greater + maxSum = std::max(maxSum, currentSum); + } + return maxSum; + } +}; \ No newline at end of file diff --git a/patterns/c++/MonotonicStack.cpp b/patterns/c++/MonotonicStack.cpp new file mode 100644 index 0000000..e7ae2c8 --- /dev/null +++ b/patterns/c++/MonotonicStack.cpp @@ -0,0 +1,39 @@ +#include +#include + +using namespace std; + +class MonotonicStack { +public: + vector nextGreaterElement(vector& nums) { + int n = nums.size(); + vector result(n, -1); // Default to -1 if no greater element exists + stack stack; // Stack stores indices + + for (int i = 0; i < n; i++) { + while (!stack.empty() && nums[i] > nums[stack.top()]) { + int index = stack.top(); + stack.pop(); + result[index] = nums[i]; + } + stack.push(i); + } + return result; + } + + vector dailyTemperatures(vector& temperatures) { + int n = temperatures.size(); + vector result(n, 0); + stack stack; // Monotonic decreasing stack + + for (int i = 0; i < n; i++) { + while (!stack.empty() && temperatures[i] > temperatures[stack.top()]) { + int prevIndex = stack.top(); + stack.pop(); + result[prevIndex] = i - prevIndex; + } + stack.push(i); + } + return result; + } +}; \ No newline at end of file diff --git a/patterns/c++/SlidingWindow.cpp b/patterns/c++/SlidingWindow.cpp new file mode 100644 index 0000000..6d12d0c --- /dev/null +++ b/patterns/c++/SlidingWindow.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +using namespace std; + +class SlidingWindow { +public: + double findMaxAverageBruteForce(vector& nums, int k) { + int n = nums.size(); + double maxAvg = INT_MIN; + + for (int i = 0; i <= n - k; i++) { + int sum = 0; + for (int j = i; j < i + k; j++) { + sum += nums[j]; + } + maxAvg = max(maxAvg, (double)sum / k); + } + return maxAvg; + } + + double findMaxAverageSlidingWindow(vector& nums, int k) { + int n = nums.size(); + int sum = 0; + + for (int i = 0; i < k; i++) { + sum += nums[i]; + } + + int maxSum = sum; + + for (int i = k; i < n; i++) { + sum += nums[i]; + sum -= nums[i - k]; + maxSum = max(maxSum, sum); + } + + return (double)maxSum / k; + } + + int lengthOfLongestSubstringSlidingWindow(string s) { + unordered_set seen; + int maxLength = 0, left = 0; + + for (int right = 0; right < s.size(); right++) { + while (seen.count(s[right])) { + seen.erase(s[left]); + left++; + } + seen.insert(s[right]); + maxLength = max(maxLength, right - left + 1); + } + return maxLength; + } + + int lengthOfLongestSubstringSlidingWindowFrequencyArray(string s) { + vector freq(128, 0); + int maxLength = 0, left = 0; + + for (int right = 0; right < s.size(); right++) { + freq[s[right]]++; + + while (freq[s[right]] > 1) { + freq[s[left]]--; + left++; + } + + maxLength = max(maxLength, right - left + 1); + } + return maxLength; + } +}; \ No newline at end of file diff --git a/patterns/c++/TwoPointers.cpp b/patterns/c++/TwoPointers.cpp new file mode 100644 index 0000000..8faea2b --- /dev/null +++ b/patterns/c++/TwoPointers.cpp @@ -0,0 +1,64 @@ +#include +#include +#include + +using namespace std; + +class TwoPointers { +public: + // Move Zeroes using Two Pointers + void moveZeroesTwoPointers(vector& nums) { + int left = 0; // Pointer for placing non-zero elements + + // Iterate with right pointer + for (int right = 0; right < nums.size(); right++) { + if (nums[right] != 0) { + // Swap elements if right pointer finds a non-zero + swap(nums[left], nums[right]); + left++; // Move left pointer forward + } + } + } + + // Brute Force approach for Container with Most Water + int maxAreaBruteForce(vector& height) { + int n = height.size(); + int maxArea = 0; + + // Check all pairs (i, j) + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + // Compute the minimum height and width + int minHeight = min(height[i], height[j]); + int width = j - i; + int area = minHeight * width; // Compute water contained + + maxArea = max(maxArea, area); // Update max water + } + } + return maxArea; + } + + // Two Pointers approach for Container with Most Water + int maxAreaTwoPointers(vector& height) { + int left = 0, right = height.size() - 1; + int maxArea = 0; + + // Move pointers toward each other + while (left < right) { + int width = right - left; // Distance between lines + int minHeight = min(height[left], height[right]); // Compute height + int area = minHeight * width; // Compute water contained + + maxArea = max(maxArea, area); // Update max water + + // Move the pointer pointing to the shorter height + if (height[left] < height[right]) { + left++; // Move left pointer forward + } else { + right--; // Move right pointer backward + } + } + return maxArea; + } +}; \ No newline at end of file diff --git a/patterns/go/monotonic_stack.go b/patterns/go/monotonic_stack.go new file mode 100644 index 0000000..1f66f4b --- /dev/null +++ b/patterns/go/monotonic_stack.go @@ -0,0 +1,46 @@ +package main + +import "fmt" + +func nextGreaterElement(nums []int) []int { + n := len(nums) + result := make([]int, n) + for i := range result { + result[i] = -1 // Default to -1 if no greater element exists + } + stack := []int{} // Stack stores indices + + for i := 0; i < n; i++ { + for len(stack) > 0 && nums[i] > nums[stack[len(stack)-1]] { + index := stack[len(stack)-1] + stack = stack[:len(stack)-1] + result[index] = nums[i] + } + stack = append(stack, i) + } + return result +} + +func dailyTemperatures(temperatures []int) []int { + n := len(temperatures) + result := make([]int, n) // Result array initialized with 0s + stack := []int{} // Monotonic decreasing stack + + for i := 0; i < n; i++ { + for len(stack) > 0 && temperatures[i] > temperatures[stack[len(stack)-1]] { + prevIndex := stack[len(stack)-1] + stack = stack[:len(stack)-1] + result[prevIndex] = i - prevIndex + } + stack = append(stack, i) + } + return result +} + +func main() { + nums := []int{2, 1, 5, 6, 2, 3} + fmt.Println(nextGreaterElement(nums)) + + temperatures := []int{73, 74, 75, 71, 69, 72, 76, 73} + fmt.Println(dailyTemperatures(temperatures)) +} diff --git a/patterns/go/sliding_window.go b/patterns/go/sliding_window.go new file mode 100644 index 0000000..056b87d --- /dev/null +++ b/patterns/go/sliding_window.go @@ -0,0 +1,81 @@ +package main + +import ( + "math" +) + +// Brute Force Approach - O(n * k) +func findMaxAverageBruteForce(nums []int, k int) float64 { + n := len(nums) + maxAvg := math.Inf(-1) + + for i := 0; i <= n-k; i++ { + sum := 0 + for j := i; j < i+k; j++ { + sum += nums[j] + } + maxAvg = math.Max(maxAvg, float64(sum)/float64(k)) + } + return maxAvg +} + +// Sliding Window Approach - O(n) +func findMaxAverageSlidingWindow(nums []int, k int) float64 { + sum := 0 + for i := 0; i < k; i++ { + sum += nums[i] + } + + maxSum := sum + + for i := k; i < len(nums); i++ { + sum += nums[i] - nums[i-k] + if sum > maxSum { + maxSum = sum + } + } + + return float64(maxSum) / float64(k) +} + +// Sliding Window for Longest Substring Without Repeating Characters +func lengthOfLongestSubstringSlidingWindow(s string) int { + seen := make(map[byte]bool) + maxLength, left := 0, 0 + + for right := 0; right < len(s); right++ { + for seen[s[right]] { + delete(seen, s[left]) + left++ + } + seen[s[right]] = true + maxLength = max(maxLength, right-left+1) + } + return maxLength +} + +// Sliding Window using Frequency Array +func lengthOfLongestSubstringSlidingWindowFrequencyArray(s string) int { + freq := make([]int, 128) + maxLength, left := 0, 0 + + for right := 0; right < len(s); right++ { + freq[s[right]]++ + + for freq[s[right]] > 1 { + freq[s[left]]-- + left++ + } + + maxLength = max(maxLength, right-left+1) + } + return maxLength +} + +// Helper function to get max of two numbers +func max(a, b int) int { + if a > b { + return a + } + return b +} diff --git a/patterns/go/two_pointers.go b/patterns/go/two_pointers.go new file mode 100644 index 0000000..1433c48 --- /dev/null +++ b/patterns/go/two_pointers.go @@ -0,0 +1,69 @@ +package main + +// Move Zeroes using Two Pointers +func moveZeroesTwoPointers(nums []int) { + left := 0 // Pointer for placing non-zero elements + + // Iterate with right pointer + for right := 0; right < len(nums); right++ { + if nums[right] != 0 { + // Swap elements if right pointer finds a non-zero + nums[left], nums[right] = nums[right], nums[left] + left++ // Move left pointer forward + } + } +} + +// Brute Force approach for Container with Most Water +func maxAreaBruteForce(height []int) int { + n := len(height) + maxArea := 0 + + // Check all pairs (i, j) + for i := 0; i < n; i++ { + for j := i + 1; j < n; j++ { + // Compute the minimum height and width + minHeight := min(height[i], height[j]) + width := j - i + area := minHeight * width // Compute water contained + + if area > maxArea { + maxArea = area // Update max water + } + } + } + return maxArea +} + +// Two Pointers approach for Container with Most Water +func maxAreaTwoPointers(height []int) int { + left, right := 0, len(height)-1 + maxArea := 0 + + // Move pointers toward each other + for left < right { + width := right - left // Distance between lines + minHeight := min(height[left], height[right]) // Compute height + area := minHeight * width // Compute water contained + + if area > maxArea { + maxArea = area // Update max water + } + + // Move the pointer pointing to the shorter height + if height[left] < height[right] { + left++ // Move left pointer forward + } else { + right-- // Move right pointer backward + } + } + return maxArea +} + +// Helper function to return the minimum of two integers +func min(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/patterns/java/MonotonicStack.java b/patterns/java/MonotonicStack.java new file mode 100644 index 0000000..920b61f --- /dev/null +++ b/patterns/java/MonotonicStack.java @@ -0,0 +1,43 @@ +package patterns.java; + +import java.util.Arrays; +import java.util.Stack; + +public class MonotonicStack { + + public int[] nextGreaterElement(int[] nums) { + int n = nums.length; + int[] result = new int[n]; // Output array + Arrays.fill(result, -1); // Default to -1 if no greater element exists + Stack stack = new Stack<>(); // Stack stores indices + + // Iterate through the array + for (int i = 0; i < n; i++) { + // While stack is not empty and current element is greater than stack top + while (!stack.isEmpty() && nums[i] > nums[stack.peek()]) { + int index = stack.pop(); // Pop the top element + result[index] = nums[i]; // The current element is the Next Greater Element + } + stack.push(i); // Push the current index onto the stack + } + return result; + } + + public int[] dailyTemperatures(int[] temperatures) { + int n = temperatures.length; + int[] result = new int[n]; // Result array initialized with 0s + Stack stack = new Stack<>(); // Monotonic decreasing stack (stores indices) + + // Iterate through the temperature array + for (int i = 0; i < n; i++) { + // While stack is not empty AND the current temperature is warmer than the temperature at stack top + while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) { + int prevIndex = stack.pop(); // Pop the previous day's index + result[prevIndex] = i - prevIndex; // Calculate the wait time + } + stack.push(i); // Push current index onto the stack + } + + return result; // Return the computed results + } +} \ No newline at end of file diff --git a/patterns/java/SlidingWindow.java b/patterns/java/SlidingWindow.java new file mode 100644 index 0000000..7fe3d79 --- /dev/null +++ b/patterns/java/SlidingWindow.java @@ -0,0 +1,90 @@ +package patterns.java; + +import java.util.HashSet; + +public class SlidingWindow { + public double findMaxAverageBruteForce(int[] nums, int k) { + int n = nums.length; + double maxAvg = Integer.MIN_VALUE; + + // Iterate through all possible subarrays of length k + for (int i = 0; i <= n - k; i++) { + int sum = 0; + + // Calculate sum of subarray starting at index i + for (int j = i; j < i + k; j++) { + sum += nums[j]; + } + + // Compute average and update maxAvg + maxAvg = Math.max(maxAvg, (double) sum / k); + } + return maxAvg; + } + + public double findMaxAverageSlidingWindow(int[] nums, int k) { + int n = nums.length; + + // Compute the sum of the first 'k' elements + int sum = 0; + for (int i = 0; i < k; i++) { + sum += nums[i]; + } + + // Initialize maxSum as the sum of the first window + int maxSum = sum; + + // Slide the window across the array + for (int i = k; i < n; i++) { + sum += nums[i]; // Add new element entering window + sum -= nums[i - k]; // Remove element leaving window + maxSum = Math.max(maxSum, sum); // Update maxSum + } + + // Return maximum average + return (double) maxSum / k; + } + + public int lengthOfLongestSubstringSlidingWindow(String s) { + int n = s.length(); + HashSet seen = new HashSet<>(); // Store characters in the current window + int maxLength = 0; + int left = 0; + + // Expand window by moving 'right' + for (int right = 0; right < n; right++) { + // If a duplicate is found, shrink the window from the left + while (seen.contains(s.charAt(right))) { + seen.remove(s.charAt(left)); + left++; + } + // Add current character to window and update max length + seen.add(s.charAt(right)); + maxLength = Math.max(maxLength, right - left + 1); + } + return maxLength; + } + + public int lengthOfLongestSubstringSlidingWindowFrequencyArray(String s) { + int n = s.length(); + int[] freq = new int[128]; // ASCII character frequency array + int maxLength = 0; + int left = 0; + + // Expand window by moving 'right' + for (int right = 0; right < n; right++) { + char currentChar = s.charAt(right); + freq[currentChar]++; // Increase frequency of the current character + + // If there is a duplicate, shrink the window from the left + while (freq[currentChar] > 1) { + freq[s.charAt(left)]--; // Remove character at left pointer + left++; // Shrink window + } + + // Update maximum window size + maxLength = Math.max(maxLength, right - left + 1); + } + return maxLength; + } +} \ No newline at end of file diff --git a/patterns/java/TopKElements.java b/patterns/java/TopKElements.java index c84c391..15946b1 100644 --- a/patterns/java/TopKElements.java +++ b/patterns/java/TopKElements.java @@ -126,7 +126,9 @@ private int getDistance(int[] point) { public int[][] kClosestPointsToOriginMaxHeapApproach(int[][] points, int k) { // Max heap with custom comparator to compare by distance - PriorityQueue maxHeap = new PriorityQueue<>((a, b) -> getDistance(b) - getDistance(a)); + PriorityQueue maxHeap = new PriorityQueue<>( + (a, b) -> Integer.compare(getDistance(b), getDistance(a)) + ); // Iterate through all points for (int[] point : points) { @@ -146,4 +148,4 @@ public int[][] kClosestPointsToOriginMaxHeapApproach(int[][] points, int k) { return result; } -} \ No newline at end of file +} diff --git a/patterns/java/TwoPointers.java b/patterns/java/TwoPointers.java new file mode 100644 index 0000000..35cb395 --- /dev/null +++ b/patterns/java/TwoPointers.java @@ -0,0 +1,59 @@ +package patterns.java; + +public class TwoPointers { + + public void moveZeroesTwoPointers(int[] nums) { + int left = 0; // Pointer for placing non-zero elements + + // Iterate with right pointer + for (int right = 0; right < nums.length; right++) { + if (nums[right] != 0) { + // Swap elements if right pointer finds a non-zero + int temp = nums[left]; + nums[left] = nums[right]; + nums[right] = temp; + left++; // Move left pointer forward + } + } + } + + public int maxAreaBruteForce(int[] height) { + int n = height.length; + int maxArea = 0; + + // Check all pairs (i, j) + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + // Height of the container + int minHeight = Math.min(height[i], height[j]); + int width = j - i; // Distance between lines + int area = minHeight * width; // Compute water contained + + maxArea = Math.max(maxArea, area); // Update max water + } + } + return maxArea; + } + + public int maxAreaTwoPointers(int[] height) { + int left = 0, right = height.length - 1; + int maxArea = 0; + + // Move pointers toward each other + while (left <= right) { + int width = right - left; // Distance between lines + int minHeight = Math.min(height[left], height[right]); + int area = minHeight * width; // Compute water contained + + maxArea = Math.max(maxArea, area); // Update max water + + // Move the pointer pointing to the shorter height + if (height[left] < height[right]) { + left++; // Move left pointer forward + } else { + right--; // Move right pointer backward + } + } + return maxArea; + } +} \ No newline at end of file diff --git a/patterns/javascript/monotonicStack.js b/patterns/javascript/monotonicStack.js new file mode 100644 index 0000000..94918c4 --- /dev/null +++ b/patterns/javascript/monotonicStack.js @@ -0,0 +1,31 @@ +class MonotonicStack { + nextGreaterElement(nums) { + let n = nums.length; + let result = new Array(n).fill(-1); // Default to -1 if no greater element exists + let stack = []; // Stack stores indices + + for (let i = 0; i < n; i++) { + while (stack.length > 0 && nums[i] > nums[stack[stack.length - 1]]) { + let index = stack.pop(); + result[index] = nums[i]; + } + stack.push(i); + } + return result; + } + + dailyTemperatures(temperatures) { + let n = temperatures.length; + let result = new Array(n).fill(0); // Result array initialized with 0s + let stack = []; // Monotonic decreasing stack + + for (let i = 0; i < n; i++) { + while (stack.length > 0 && temperatures[i] > temperatures[stack[stack.length - 1]]) { + let prevIndex = stack.pop(); + result[prevIndex] = i - prevIndex; + } + stack.push(i); + } + return result; + } +} \ No newline at end of file diff --git a/patterns/javascript/slidingWindow.js b/patterns/javascript/slidingWindow.js new file mode 100644 index 0000000..2e80ef0 --- /dev/null +++ b/patterns/javascript/slidingWindow.js @@ -0,0 +1,62 @@ +class SlidingWindow { + // Brute Force Approach - O(n * k) + findMaxAverageBruteForce(nums, k) { + let maxAvg = -Infinity; + + for (let i = 0; i <= nums.length - k; i++) { + let sum = 0; + for (let j = i; j < i + k; j++) { + sum += nums[j]; + } + maxAvg = Math.max(maxAvg, sum / k); + } + return maxAvg; + } + + // Sliding Window Approach - O(n) + findMaxAverageSlidingWindow(nums, k) { + let sum = nums.slice(0, k).reduce((a, b) => a + b, 0); + let maxSum = sum; + + for (let i = k; i < nums.length; i++) { + sum += nums[i] - nums[i - k]; + maxSum = Math.max(maxSum, sum); + } + + return maxSum / k; + } + + // Sliding Window for Longest Substring Without Repeating Characters + lengthOfLongestSubstringSlidingWindow(s) { + let seen = new Set(); + let maxLength = 0, left = 0; + + for (let right = 0; right < s.length; right++) { + while (seen.has(s[right])) { + seen.delete(s[left]); + left++; + } + seen.add(s[right]); + maxLength = Math.max(maxLength, right - left + 1); + } + return maxLength; + } + + // Sliding Window using Frequency Array + lengthOfLongestSubstringSlidingWindowFrequencyArray(s) { + let freq = new Array(128).fill(0); + let maxLength = 0, left = 0; + + for (let right = 0; right < s.length; right++) { + freq[s.charCodeAt(right)]++; + + while (freq[s.charCodeAt(right)] > 1) { + freq[s.charCodeAt(left)]--; + left++; + } + + maxLength = Math.max(maxLength, right - left + 1); + } + return maxLength; + } +} \ No newline at end of file diff --git a/patterns/javascript/twoPointers.js b/patterns/javascript/twoPointers.js new file mode 100644 index 0000000..5c46a59 --- /dev/null +++ b/patterns/javascript/twoPointers.js @@ -0,0 +1,68 @@ +class TwoPointers { + /** + * Move Zeroes using Two Pointers + * @param {number[]} nums - Input array + */ + moveZeroesTwoPointers(nums) { + let left = 0; // Pointer for placing non-zero elements + + // Iterate with right pointer + for (let right = 0; right < nums.length; right++) { + if (nums[right] !== 0) { + // Swap elements if right pointer finds a non-zero + [nums[left], nums[right]] = [nums[right], nums[left]]; + left++; // Move left pointer forward + } + } + } + + /** + * Brute Force approach for Container with Most Water + * @param {number[]} height - Array of heights + * @return {number} - Maximum water that can be contained + */ + maxAreaBruteForce(height) { + let maxArea = 0; + let n = height.length; + + // Check all pairs (i, j) + for (let i = 0; i < n; i++) { + for (let j = i + 1; j < n; j++) { + // Compute the minimum height and width + let minHeight = Math.min(height[i], height[j]); + let width = j - i; + let area = minHeight * width; // Compute water contained + + maxArea = Math.max(maxArea, area); // Update max water + } + } + return maxArea; + } + + /** + * Two Pointers approach for Container with Most Water + * @param {number[]} height - Array of heights + * @return {number} - Maximum water that can be contained + */ + maxAreaTwoPointers(height) { + let left = 0, right = height.length - 1; + let maxArea = 0; + + // Move pointers toward each other + while (left < right) { + let width = right - left; // Distance between lines + let minHeight = Math.min(height[left], height[right]); // Compute height + let area = minHeight * width; // Compute water contained + + maxArea = Math.max(maxArea, area); // Update max water + + // Move the pointer pointing to the shorter height + if (height[left] < height[right]) { + left++; // Move left pointer forward + } else { + right--; // Move right pointer backward + } + } + return maxArea; + } +} \ No newline at end of file diff --git a/patterns/python/monotonic_stack.py b/patterns/python/monotonic_stack.py new file mode 100644 index 0000000..62e51ce --- /dev/null +++ b/patterns/python/monotonic_stack.py @@ -0,0 +1,26 @@ +class MonotonicStack: + def next_greater_element(self, nums): + n = len(nums) + result = [-1] * n # Default to -1 if no greater element exists + stack = [] # Stack stores indices + + for i in range(n): + while stack and nums[i] > nums[stack[-1]]: + index = stack.pop() + result[index] = nums[i] + stack.append(i) + + return result + + def daily_temperatures(self, temperatures): + n = len(temperatures) + result = [0] * n # Result array initialized with 0s + stack = [] # Monotonic decreasing stack + + for i in range(n): + while stack and temperatures[i] > temperatures[stack[-1]]: + prev_index = stack.pop() + result[prev_index] = i - prev_index + stack.append(i) + + return result \ No newline at end of file diff --git a/patterns/python/sliding_window.py b/patterns/python/sliding_window.py new file mode 100644 index 0000000..b42e33d --- /dev/null +++ b/patterns/python/sliding_window.py @@ -0,0 +1,46 @@ +class SlidingWindow: + def find_max_average_brute_force(self, nums, k): + max_avg = float('-inf') + + for i in range(len(nums) - k + 1): + max_avg = max(max_avg, sum(nums[i:i + k]) / k) + + return max_avg + + def find_max_average_sliding_window(self, nums, k): + sum_window = sum(nums[:k]) + max_sum = sum_window + + for i in range(k, len(nums)): + sum_window += nums[i] - nums[i - k] + max_sum = max(max_sum, sum_window) + + return max_sum / k + + def length_of_longest_substring_sliding_window(self, s): + seen = set() + max_length = left = 0 + + for right in range(len(s)): + while s[right] in seen: + seen.remove(s[left]) + left += 1 + seen.add(s[right]) + max_length = max(max_length, right - left + 1) + + return max_length + + def length_of_longest_substring_sliding_window_frequency_array(self, s): + freq = [0] * 128 + max_length = left = 0 + + for right in range(len(s)): + freq[ord(s[right])] += 1 + + while freq[ord(s[right])] > 1: + freq[ord(s[left])] -= 1 + left += 1 + + max_length = max(max_length, right - left + 1) + + return max_length \ No newline at end of file diff --git a/patterns/python/two_pointers.py b/patterns/python/two_pointers.py new file mode 100644 index 0000000..3e874f0 --- /dev/null +++ b/patterns/python/two_pointers.py @@ -0,0 +1,48 @@ +class TwoPointers: + # Move Zeroes using Two Pointers + def move_zeroes_two_pointers(self, nums): + left = 0 # Pointer for placing non-zero elements + + # Iterate with right pointer + for right in range(len(nums)): + if nums[right] != 0: + # Swap elements if right pointer finds a non-zero + nums[left], nums[right] = nums[right], nums[left] + left += 1 # Move left pointer forward + + # Brute Force approach for Container with Most Water + def max_area_brute_force(self, height): + n = len(height) + max_area = 0 + + # Check all pairs (i, j) + for i in range(n): + for j in range(i + 1, n): + # Compute the minimum height and width + min_height = min(height[i], height[j]) + width = j - i + area = min_height * width # Compute water contained + + max_area = max(max_area, area) # Update max water + return max_area + + # Two Pointers approach for Container with Most Water + def max_area_two_pointers(self, height): + left, right = 0, len(height) - 1 + max_area = 0 + + # Move pointers toward each other + while left < right: + width = right - left # Distance between lines + min_height = min(height[left], height[right]) # Compute height + area = min_height * width # Compute water contained + + max_area = max(max_area, area) # Update max water + + # Move the pointer pointing to the shorter height + if height[left] < height[right]: + left += 1 # Move left pointer forward + else: + right -= 1 # Move right pointer backward + + return max_area \ No newline at end of file diff --git a/patterns/typescript/monotonicStack.ts b/patterns/typescript/monotonicStack.ts new file mode 100644 index 0000000..a878002 --- /dev/null +++ b/patterns/typescript/monotonicStack.ts @@ -0,0 +1,31 @@ +class MonotonicStack { + nextGreaterElement(nums: number[]): number[] { + let n = nums.length; + let result: number[] = new Array(n).fill(-1); // Default to -1 if no greater element exists + let stack: number[] = []; // Stack stores indices + + for (let i = 0; i < n; i++) { + while (stack.length > 0 && nums[i] > nums[stack[stack.length - 1]]) { + let index = stack.pop()!; + result[index] = nums[i]; + } + stack.push(i); + } + return result; + } + + dailyTemperatures(temperatures: number[]): number[] { + let n = temperatures.length; + let result: number[] = new Array(n).fill(0); // Result array initialized with 0s + let stack: number[] = []; // Monotonic decreasing stack + + for (let i = 0; i < n; i++) { + while (stack.length > 0 && temperatures[i] > temperatures[stack[stack.length - 1]]) { + let prevIndex = stack.pop()!; + result[prevIndex] = i - prevIndex; + } + stack.push(i); + } + return result; + } +} \ No newline at end of file diff --git a/patterns/typescript/slidingWindow.ts b/patterns/typescript/slidingWindow.ts new file mode 100644 index 0000000..86a2c8d --- /dev/null +++ b/patterns/typescript/slidingWindow.ts @@ -0,0 +1,62 @@ +class SlidingWindow { + // Brute Force Approach - O(n * k) + findMaxAverageBruteForce(nums: number[], k: number): number { + let maxAvg = -Infinity; + + for (let i = 0; i <= nums.length - k; i++) { + let sum = 0; + for (let j = i; j < i + k; j++) { + sum += nums[j]; + } + maxAvg = Math.max(maxAvg, sum / k); + } + return maxAvg; + } + + // Sliding Window Approach - O(n) + findMaxAverageSlidingWindow(nums: number[], k: number): number { + let sum = nums.slice(0, k).reduce((a, b) => a + b, 0); + let maxSum = sum; + + for (let i = k; i < nums.length; i++) { + sum += nums[i] - nums[i - k]; + maxSum = Math.max(maxSum, sum); + } + + return maxSum / k; + } + + // Sliding Window for Longest Substring Without Repeating Characters + lengthOfLongestSubstringSlidingWindow(s: string): number { + let seen = new Set(); + let maxLength = 0, left = 0; + + for (let right = 0; right < s.length; right++) { + while (seen.has(s[right])) { + seen.delete(s[left]); + left++; + } + seen.add(s[right]); + maxLength = Math.max(maxLength, right - left + 1); + } + return maxLength; + } + + // Sliding Window using Frequency Array + lengthOfLongestSubstringSlidingWindowFrequencyArray(s: string): number { + let freq = new Array(128).fill(0); + let maxLength = 0, left = 0; + + for (let right = 0; right < s.length; right++) { + freq[s.charCodeAt(right)]++; + + while (freq[s.charCodeAt(right)] > 1) { + freq[s.charCodeAt(left)]--; + left++; + } + + maxLength = Math.max(maxLength, right - left + 1); + } + return maxLength; + } +} \ No newline at end of file diff --git a/patterns/typescript/twoPointers.ts b/patterns/typescript/twoPointers.ts new file mode 100644 index 0000000..8587625 --- /dev/null +++ b/patterns/typescript/twoPointers.ts @@ -0,0 +1,57 @@ +class TwoPointers { + // Move Zeroes using Two Pointers + moveZeroesTwoPointers(nums: number[]): void { + let left = 0; // Pointer for placing non-zero elements + + // Iterate with right pointer + for (let right = 0; right < nums.length; right++) { + if (nums[right] !== 0) { + // Swap elements if right pointer finds a non-zero + [nums[left], nums[right]] = [nums[right], nums[left]]; + left++; // Move left pointer forward + } + } + } + + // Brute Force approach for Container with Most Water + maxAreaBruteForce(height: number[]): number { + let maxArea = 0; + let n = height.length; + + // Check all pairs (i, j) + for (let i = 0; i < n; i++) { + for (let j = i + 1; j < n; j++) { + // Compute the minimum height and width + let minHeight = Math.min(height[i], height[j]); + let width = j - i; + let area = minHeight * width; // Compute water contained + + maxArea = Math.max(maxArea, area); // Update max water + } + } + return maxArea; + } + + // Two Pointers approach for Container with Most Water + maxAreaTwoPointers(height: number[]): number { + let left = 0, right = height.length - 1; + let maxArea = 0; + + // Move pointers toward each other + while (left < right) { + let width = right - left; // Distance between lines + let minHeight = Math.min(height[left], height[right]); // Compute height + let area = minHeight * width; // Compute water contained + + maxArea = Math.max(maxArea, area); // Update max water + + // Move the pointer pointing to the shorter height + if (height[left] < height[right]) { + left++; // Move left pointer forward + } else { + right--; // Move right pointer backward + } + } + return maxArea; + } +} \ No newline at end of file