diff --git a/README.md b/README.md index 6b9c46e..2ea2fc4 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,119 @@ -# Awesome LeetCode Resources -This repository contains LeetCode resources which are useful during interview preparation. +

+ +

+

+ Join Free Newsletter +

-## Fundamental Concepts -- [LinkedIn List](https://leetcode.com/discuss/study-guide/1800120/become-master-in-linked-list) +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) + +## 💡 Tips +- [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/) +- [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) - [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) - [Heaps](https://medium.com/basecs/learning-to-love-heaps-cef2b273a238) - [Recursion](https://leetcode.com/discuss/study-guide/1733447/become-master-in-recursion) +- [Backtracking](https://medium.com/algorithms-and-leetcode/backtracking-e001561b9f28) - [Trees](https://leetcode.com/discuss/study-guide/1820334/Become-Master-in-Tree) - [Tries](https://medium.com/basecs/trying-to-understand-tries-3ec6bede0014) - [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) - [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) -- [Dijkstra Algorithm](https://medium.com/basecs/finding-the-shortest-path-with-a-little-help-from-dijkstra-613149fbdc8e) +- [Union-Find](https://leetcode.com/discuss/general-discussion/1072418/Disjoint-Set-Union-(DSU)Union-Find-A-Complete-Guide) +- [Dijkstra Algorithm](https://leetcode.com/discuss/study-guide/1059477/A-guide-to-Dijkstra's-Algorithm) +- [Minimum Spanning Tree](https://www.hackerearth.com/practice/algorithms/graphs/minimum-spanning-tree/tutorial/) -## Patterns -- [14 Coding Interview Patterns](https://hackernoon.com/14-patterns-to-ace-any-coding-interview-question-c5bb3357f6ed) -- [Sliding Window patterns](https://leetcode.com/problems/frequency-of-the-most-frequent-element/solutions/1175088/C++-Maximum-Sliding-Window-Cheatsheet-Template/) -- [Two Pointers Patterns](https://leetcode.com/discuss/study-guide/1688903/Solved-all-two-pointers-problems-in-100-days) -- [Substring Problem Patterns](https://leetcode.com/problems/minimum-window-substring/solutions/26808/Here-is-a-10-line-template-that-can-solve-most-'substring'-problems/) -- [Dynamic Programming Patterns](https://leetcode.com/discuss/study-guide/458695/Dynamic-Programming-Patterns) -- [Binary Search Patterns](https://leetcode.com/discuss/study-guide/786126/Python-Powerful-Ultimate-Binary-Search-Template.-Solved-many-problems) -- [Backtracking Patterns](https://leetcode.com/problems/permutations/solutions/18239/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partioning)/) +## 🚀 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) +- [Two Pointers Pattern](https://www.youtube.com/watch?v=QzZ7nmouLTI) +- [Sliding Window Pattern](https://blog.algomaster.io/p/f4412a17-7a3a-4d0b-8e39-9ea8f429bf7c) +- [Prefix Sum Pattern](https://www.youtube.com/watch?v=yuws7YK0Yng) +- [Fast and Slow Pointers Pattern](https://www.youtube.com/watch?v=b139yf7Ik-E) +- [Top 'K' Elements Pattern](https://www.youtube.com/watch?v=6_v6OoxvMOE) +- [Kadane's Algorithm](https://www.youtube.com/watch?v=NUWAXbSlsws) +- [Sliding Window Pattern](https://www.youtube.com/watch?v=y2d0VHdvfdc) +- [Linked List In-place Reversal Pattern](https://www.youtube.com/watch?v=auoTGovuo9A) +- [Monotonic Stack Pattern](https://www.youtube.com/watch?v=DtJVwbbicjQ) +- [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) - [Tree Patterns](https://leetcode.com/discuss/study-guide/937307/Iterative-or-Recursive-or-DFS-and-BFS-Tree-Traversal-or-In-Pre-Post-and-LevelOrder-or-Views) - [Tree Iterative Traversal](https://medium.com/leetcode-patterns/leetcode-pattern-0-iterative-traversals-on-trees-d373568eb0ec) - [Tree Question Pattern](https://leetcode.com/discuss/study-guide/2879240/TREE-QUESTION-PATTERN-2023-oror-TREE-STUDY-GUIDE) - [Graph Patterns](https://leetcode.com/discuss/study-guide/655708/Graph-For-Beginners-Problems-or-Pattern-or-Sample-Solutions) -- [Monotonic Stack Patterns](https://leetcode.com/discuss/study-guide/2347639/A-comprehensive-guide-and-template-for-monotonic-stack-based-problems) -- [Bit Manipulation Patterns](https://leetcode.com/discuss/study-guide/4282051/all-types-of-patterns-for-bits-manipulations-and-how-to-use-it) -- [String Question Patterns](https://leetcode.com/discuss/study-guide/2001789/Collections-of-Important-String-questions-Pattern) - [DFS + BFS Patterns (1)](https://medium.com/leetcode-patterns/leetcode-pattern-1-bfs-dfs-25-of-the-problems-part-1-519450a84353) - [DFS + BFS Patterns (2)](https://medium.com/leetcode-patterns/leetcode-pattern-2-dfs-bfs-25-of-the-problems-part-2-a5b269597f52) -- [Stock Series Patterns](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/solutions/108870/most-consistent-ways-of-dealing-with-the-series-of-stock-problems/) -## LeetCode Extensions -- [LeetCode Timer](https://chromewebstore.google.com/detail/leetcode-timer/gfkgelnlcnomnahkfmhemgpahgmibofd): Easily time your leetcode practise sessions with automatic time setting based on difficulty. -- [LeetCode Video Solutions](https://chromewebstore.google.com/detail/leetcode-video-solutions/ilnmgkahgjdpkoliooildngldmilhelm): Watch free LeetCode video ▶ solutions on the problem page itself. -- [LeetCode Format](https://chromewebstore.google.com/detail/leetcode-format/imogghebhifnnlgogigikjecilkicfpp): Adds Format code button on leetcode to format the code using Prettier code formatter. -- [LeetHub v2](https://chromewebstore.google.com/detail/leethub-v2/mhanfgfagplhgemhjfeolkkdidbakocm?hl=en): Automatically integrate your Leetcode & GeeksforGeeks submissions to GitHub. -- [LeetCode VS Code Extension](https://marketplace.visualstudio.com/items?itemName=LeetCode.vscode-leetcode): Solve LeetCode problems in VS Code. +## 📝 Must-Read Leetcode Articles +- [Sliding Window Template](https://leetcode.com/problems/frequency-of-the-most-frequent-element/solutions/1175088/C++-Maximum-Sliding-Window-Cheatsheet-Template/) +- [Two Pointers Patterns](https://leetcode.com/discuss/study-guide/1688903/Solved-all-two-pointers-problems-in-100-days) +- [Collections of Important String Questions](https://leetcode.com/discuss/study-guide/2001789/Collections-of-Important-String-questions-Pattern) +- [Substring Problem Template](https://leetcode.com/problems/minimum-window-substring/solutions/26808/Here-is-a-10-line-template-that-can-solve-most-'substring'-problems/) +- [Binary Search Template](https://leetcode.com/discuss/study-guide/786126/Python-Powerful-Ultimate-Binary-Search-Template.-Solved-many-problems) +- [A General Approach to Backtracking Questions](https://leetcode.com/problems/permutations/solutions/18239/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partioning)/) +- [Monotonic Stack Template](https://leetcode.com/discuss/study-guide/2347639/A-comprehensive-guide-and-template-for-monotonic-stack-based-problems) +- [Heap Patterns](https://leetcode.com/discuss/general-discussion/1127238/master-heap-by-solving-23-questions-in-4-patterns-category) +- [Bit Manipulation Patterns](https://leetcode.com/discuss/study-guide/4282051/all-types-of-patterns-for-bits-manipulations-and-how-to-use-it) +- [Dynamic Programming Patterns](https://leetcode.com/discuss/study-guide/458695/Dynamic-Programming-Patterns) +- [Stock Series Patterns](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/solutions/108870/most-consistent-ways-of-dealing-with-the-series-of-stock-problems/) -## Curated Problems -- [Blind 75](https://neetcode.io/practice) +## ✅ Curated Problems +- [AlgoMaster 300](https://algomaster.io/practice/dsa-patterns) +- [Blind 75](https://leetcode.com/discuss/general-discussion/460599/blind-75-leetcode-questions) - [Leetcode Top 100 Liked](https://leetcode.com/studyplan/top-100-liked/) - [Leetcode Top Interview 150](https://leetcode.com/studyplan/top-interview-150/) -- [Leetcode 75](https://leetcode.com/studyplan/leetcode-75/) -## Books -- [Data Structures And Algorithms Made Easy](https://www.amazon.com/Data-Structures-Algorithms-Made-Easy-ebook/dp/B0CBW278NC/) -- [Cracking the Coding Interview](https://www.amazon.com/Cracking-Coding-Interview-Programming-Questions/dp/0984782850/) +## 📺 YouTube Playlist +- [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) +- [William Fiset's Graphs Playlist](https://www.youtube.com/playlist?list=PLDV1Zeh2NRsDGO4--qE8yH72HFL1Km93P) +- [Tushar Roy's Dynamic Programming Playlist](https://www.youtube.com/playlist?list=PLrmLmBdmIlpsHaNTPP_jHHDx_os9ItYXr) -## Courses +## 📇 Courses - [Coursera - Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1) - [Coursera - Algorithms, Part 2](https://www.coursera.org/learn/algorithms-part2) -## Must-Do Problems (Topic Wise) - - Work in progress. Will publish soon. +## 📚 Books +- [Data Structures And Algorithms Made Easy](https://www.amazon.in/dp/B08CMLS7LZ) +- [Cracking the Coding Interview](https://www.amazon.in/dp/0984782850) +## 📩 Newsletter +- [AlgoMaster Newsletter](https://blog.algomaster.io/) + +## 🔎 Visualization +- [VisuAlgo](https://visualgo.net/en) +- [Algo-lens: Visualize leetcode problems](https://github.com/jaroslaw-weber/algo-lens) + +## 📎 LeetCode Extensions +- [LeetCode Timer](https://chromewebstore.google.com/detail/leetcode-timer/gfkgelnlcnomnahkfmhemgpahgmibofd): Easily time your leetcode practise sessions with automatic time setting based on difficulty. +- [LeetCode Video Solutions](https://chromewebstore.google.com/detail/leetcode-video-solutions/ilnmgkahgjdpkoliooildngldmilhelm): Watch free LeetCode video ▶ solutions on the problem page itself. +- [LeetCode Format](https://chromewebstore.google.com/detail/leetcode-format/imogghebhifnnlgogigikjecilkicfpp): Adds Format code button on leetcode to format the code using Prettier code formatter. +- [LeetHub v2](https://chromewebstore.google.com/detail/leethub-v2/mhanfgfagplhgemhjfeolkkdidbakocm?hl=en): Automatically integrate your Leetcode & GeeksforGeeks submissions to GitHub. +- [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/images/leetcode-repo-logo.png b/images/leetcode-repo-logo.png new file mode 100644 index 0000000..ce6211c Binary files /dev/null and b/images/leetcode-repo-logo.png differ diff --git a/patterns/c#/FastAndSlowPointers.cs b/patterns/c#/FastAndSlowPointers.cs new file mode 100644 index 0000000..280276d --- /dev/null +++ b/patterns/c#/FastAndSlowPointers.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; + +public class ListNode { + public int val; + public ListNode next; + public ListNode(int x) { + val = x; + next = null; + } +} + +public class FastAndSlowPointers { + // LeetCode 141 - Linked List Cycle (HashSet Approach) + public bool HasCycleHashSetApproach(ListNode head) { + HashSet visited = new HashSet(); + ListNode current = head; + while (current != null) { + if (visited.Contains(current)) { + return true; // Cycle detected + } + visited.Add(current); + current = current.next; + } + return false; // No cycle + } + + // LeetCode 141 - Linked List Cycle (Fast and Slow Pointer Approach) + public bool HasCycleFastAndSlowPointersApproach(ListNode head) { + if (head == null || head.next == null) return false; + ListNode slow = head, fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + if (slow == fast) return true; + } + return false; + } + + // LeetCode 876 - Middle of the Linked List (Counting Approach) + public ListNode MiddleNodeCountingApproach(ListNode head) { + int count = 0; + ListNode current = head; + while (current != null) { + count++; + current = current.next; + } + current = head; + for (int i = 0; i < count / 2; i++) { + current = current.next; + } + return current; + } + + // LeetCode 876 - Middle of the Linked List (Fast and Slow Pointer Approach) + public ListNode MiddleNodeFastAndSlowPointerApproach(ListNode head) { + ListNode slow = head, fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + // LeetCode 202 - Happy Number (HashSet Approach) + private int GetSumOfSquares(int n) { + int sum = 0; + while (n > 0) { + int digit = n % 10; + sum += digit * digit; + n /= 10; + } + return sum; + } + + public bool IsHappyHashSetApproach(int n) { + HashSet seen = new HashSet(); + while (n != 1 && !seen.Contains(n)) { + seen.Add(n); + n = GetSumOfSquares(n); + } + return n == 1; + } + + // LeetCode 202 - Happy Number (Fast and Slow Pointer Approach) + public bool IsHappyFastAndSlowPointersApproach(int n) { + int slow = n; + int fast = GetSumOfSquares(n); + while (fast != 1 && slow != fast) { + slow = GetSumOfSquares(slow); + fast = GetSumOfSquares(GetSumOfSquares(fast)); + } + return fast == 1; + } +} \ No newline at end of file diff --git a/patterns/c#/KadaneAlgorithm.cs b/patterns/c#/KadaneAlgorithm.cs new file mode 100644 index 0000000..f27991b --- /dev/null +++ b/patterns/c#/KadaneAlgorithm.cs @@ -0,0 +1,14 @@ +using System; + +public class KadaneAlgorithm { + public int MaxSubArray(int[] nums) { + int currentSum = nums[0]; + int maxSum = nums[0]; + + for (int i = 1; i < nums.Length; i++) { + currentSum = Math.Max(nums[i], currentSum + nums[i]); + maxSum = Math.Max(maxSum, currentSum); + } + return maxSum; + } +} \ No newline at end of file diff --git a/patterns/c#/LevelOrderTraversal.cs b/patterns/c#/LevelOrderTraversal.cs new file mode 100644 index 0000000..05b2a53 --- /dev/null +++ b/patterns/c#/LevelOrderTraversal.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; + +public class TreeNode { + public int val; + public TreeNode left; + public TreeNode right; + + public TreeNode(int x) { + val = x; + } +} + +public class LevelOrderTraversal { + public void LevelOrder(TreeNode root) { + if (root == null) return; + + Queue queue = new Queue(); + queue.Enqueue(root); + + while (queue.Count > 0) { + TreeNode node = queue.Dequeue(); + Console.Write(node.val + " "); // Process the node by printing its value + + // Add the left and right children to the queue, if they exist + if (node.left != null) queue.Enqueue(node.left); + if (node.right != null) queue.Enqueue(node.right); + } + } +} \ No newline at end of file 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#/ReverseList.cs b/patterns/c#/ReverseList.cs new file mode 100644 index 0000000..1dd3572 --- /dev/null +++ b/patterns/c#/ReverseList.cs @@ -0,0 +1,23 @@ +public class ListNode { + public int val; + public ListNode next; + public ListNode(int val = 0, ListNode next = null) { + this.val = val; + this.next = next; + } +} + +public class Solution { + public ListNode ReverseList(ListNode head) { + ListNode prev = null; + ListNode curr = head; + + while (curr != null) { + ListNode next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; + } +} \ 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#/TopKElements.cs b/patterns/c#/TopKElements.cs new file mode 100644 index 0000000..7b0b715 --- /dev/null +++ b/patterns/c#/TopKElements.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +public class TopKElements { + + // K Largest Elements using Sorting + public int[] KLargestElementsSortingApproach(int[] nums, int k) { + Array.Sort(nums, (a, b) => b.CompareTo(a)); + return nums.Take(k).ToArray(); + } + + // K Largest Elements using Max Heap + public int[] KLargestElementsMaxHeapApproach(int[] nums, int k) { + PriorityQueue maxHeap = new PriorityQueue(Comparer.Create((a, b) => b - a)); + foreach (var num in nums) { + maxHeap.Enqueue(num, num); + } + var result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = maxHeap.Dequeue(); + } + return result; + } + + // K Largest Elements using Min Heap + public int[] KLargestElementsMinHeapApproach(int[] nums, int k) { + PriorityQueue minHeap = new PriorityQueue(); + for (int i = 0; i < k; i++) { + minHeap.Enqueue(nums[i], nums[i]); + } + for (int i = k; i < nums.Length; i++) { + minHeap.Enqueue(nums[i], nums[i]); + if (minHeap.Count > k) { + minHeap.Dequeue(); + } + } + var result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = minHeap.Dequeue(); + } + return result; + } + + // Top K Frequent Elements using Sorting + public int[] TopKFrequentElementsSortingApproach(int[] nums, int k) { + var frequencyMap = new Dictionary(); + foreach (var num in nums) { + if (!frequencyMap.ContainsKey(num)) { + frequencyMap[num] = 0; + } + frequencyMap[num]++; + } + + var sortedEntries = frequencyMap.OrderByDescending(e => e.Value).Take(k).Select(e => e.Key).ToArray(); + return sortedEntries; + } + + // Top K Frequent Elements using Min Heap + public int[] TopKFrequentElementsMinHeapApproach(int[] nums, int k) { + var frequencyMap = new Dictionary(); + foreach (var num in nums) { + if (!frequencyMap.ContainsKey(num)) { + frequencyMap[num] = 0; + } + frequencyMap[num]++; + } + + var minHeap = new PriorityQueue(Comparer.Create((a, b) => a.CompareTo(b))); + foreach (var entry in frequencyMap) { + minHeap.Enqueue(entry.Key, entry.Value); + if (minHeap.Count > k) { + minHeap.Dequeue(); + } + } + + var result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = minHeap.Dequeue(); + } + return result; + } + + // K Closest Points to Origin using Max Heap + private int GetDistance(int[] point) { + return point[0] * point[0] + point[1] * point[1]; + } + + public int[][] KClosestPointsToOriginMaxHeapApproach(int[][] points, int k) { + PriorityQueue maxHeap = new PriorityQueue(Comparer.Create((a, b) => b - a)); + foreach (var point in points) { + maxHeap.Enqueue(point, GetDistance(point)); + if (maxHeap.Count > k) { + maxHeap.Dequeue(); + } + } + var result = new int[k][]; + for (int i = 0; i < k; i++) { + result[i] = maxHeap.Dequeue(); + } + return result; + } +} \ 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++/FastAndSlowPointers.cpp b/patterns/c++/FastAndSlowPointers.cpp new file mode 100644 index 0000000..b296339 --- /dev/null +++ b/patterns/c++/FastAndSlowPointers.cpp @@ -0,0 +1,100 @@ +#include +using namespace std; + +class ListNode { +public: + int val; + ListNode* next; + ListNode(int x) : val(x), next(nullptr) {} +}; + +class FastAndSlowPointers { +public: + // LeetCode 141 - Linked List Cycle (HashSet Approach) + bool hasCycleHashSetApproach(ListNode* head) { + unordered_set visited; + ListNode* current = head; + while (current != nullptr) { + if (visited.find(current) != visited.end()) { + return true; // Cycle detected + } + visited.insert(current); + current = current->next; + } + return false; // No cycle + } + + // LeetCode 141 - Linked List Cycle (Fast and Slow Pointer Approach) + bool hasCycleFastAndSlowPointersApproach(ListNode* head) { + if (head == nullptr || head->next == nullptr) { + return false; + } + ListNode* slow = head; + ListNode* fast = head; + while (fast != nullptr && fast->next != nullptr) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) { + return true; // Cycle detected + } + } + return false; // No cycle + } + + // LeetCode 876 - Middle of the Linked List (Counting Approach) + ListNode* middleNodeCountingApproach(ListNode* head) { + int count = 0; + ListNode* current = head; + while (current != nullptr) { + count++; + current = current->next; + } + current = head; + for (int i = 0; i < count / 2; i++) { + current = current->next; + } + return current; + } + + // LeetCode 876 - Middle of the Linked List (Fast and Slow Pointer Approach) + ListNode* middleNodeFastAndSlowPointerApproach(ListNode* head) { + ListNode* slow = head; + ListNode* fast = head; + while (fast != nullptr && fast->next != nullptr) { + slow = slow->next; + fast = fast->next->next; + } + return slow; + } + + // LeetCode 202 - Happy Number (HashSet Approach) + int getSumOfSquares(int n) { + int sum = 0; + while (n > 0) { + int digit = n % 10; + sum += digit * digit; + n /= 10; + } + return sum; + } + + bool isHappyHashSetApproach(int n) { + unordered_set seen; + while (n != 1 && seen.find(n) == seen.end()) { + seen.insert(n); + n = getSumOfSquares(n); + } + return n == 1; + } + + // LeetCode 202 - Happy Number (Fast and Slow Pointer Approach) + bool isHappyFastAndSlowPointersApproach(int n) { + int slow = n; + int fast = getSumOfSquares(n); + while (fast != 1 && slow != fast) { + slow = getSumOfSquares(slow); + fast = getSumOfSquares(getSumOfSquares(fast)); + } + return fast == 1; + } +}; \ No newline at end of file diff --git a/patterns/c++/KadaneAlgorithm.cpp b/patterns/c++/KadaneAlgorithm.cpp new file mode 100644 index 0000000..609f6ed --- /dev/null +++ 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++/LevelOrderTraversal.cpp b/patterns/c++/LevelOrderTraversal.cpp new file mode 100644 index 0000000..d32a116 --- /dev/null +++ b/patterns/c++/LevelOrderTraversal.cpp @@ -0,0 +1,32 @@ +#include +#include +using namespace std; + +// Definition for a binary tree node. +struct TreeNode { + int val; + TreeNode* left; + TreeNode* right; + + TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} +}; + +class LevelOrderTraversal { +public: + void levelOrder(TreeNode* root) { + if (root == nullptr) return; + + queue q; + q.push(root); + + while (!q.empty()) { + TreeNode* node = q.front(); + q.pop(); + cout << node->val << " "; // Process the node by printing its value + + // Add the left and right children to the queue, if they exist + if (node->left != nullptr) q.push(node->left); + if (node->right != nullptr) q.push(node->right); + } + } +}; \ 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++/ReverseList.cpp b/patterns/c++/ReverseList.cpp new file mode 100644 index 0000000..1740054 --- /dev/null +++ b/patterns/c++/ReverseList.cpp @@ -0,0 +1,18 @@ +struct ListNode { + int val; + ListNode* next; + ListNode(int x) : val(x), next(nullptr) {} +}; + +ListNode* reverseList(ListNode* head) { + ListNode* prev = nullptr; + ListNode* curr = head; + + while (curr != nullptr) { + ListNode* next = curr->next; + curr->next = prev; + prev = curr; + curr = next; + } + return prev; +} \ 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++/TopKElements.cpp b/patterns/c++/TopKElements.cpp new file mode 100644 index 0000000..71625a6 --- /dev/null +++ b/patterns/c++/TopKElements.cpp @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include + +using namespace std; + +class TopKElements { +public: + // K Largest Elements using Sorting + vector kLargestElementsSortingAppraoch(vector& nums, int k) { + sort(nums.begin(), nums.end(), greater()); + return vector(nums.begin(), nums.begin() + k); + } + + // K Largest Elements using Max Heap + vector kLargestElementsMaxHeapAppraoch(vector& nums, int k) { + priority_queue maxHeap(nums.begin(), nums.end()); + vector result; + for (int i = 0; i < k; i++) { + result.push_back(maxHeap.top()); + maxHeap.pop(); + } + return result; + } + + // K Largest Elements using Min Heap + vector kLargestElementsMinHeapAppraoch(vector& nums, int k) { + priority_queue, greater> minHeap; + for (int i = 0; i < k; i++) { + minHeap.push(nums[i]); + } + for (int i = k; i < nums.size(); i++) { + minHeap.push(nums[i]); + if (minHeap.size() > k) { + minHeap.pop(); + } + } + vector result; + while (!minHeap.empty()) { + result.push_back(minHeap.top()); + minHeap.pop(); + } + return result; + } + + // Top K Frequent Elements using Sorting + vector topKFrequentElementsSortingApproach(vector& nums, int k) { + unordered_map frequencyMap; + for (int num : nums) { + frequencyMap[num]++; + } + + vector> freqVec(frequencyMap.begin(), frequencyMap.end()); + sort(freqVec.begin(), freqVec.end(), [](pair& a, pair& b) { + return b.second < a.second; + }); + + vector result; + for (int i = 0; i < k; i++) { + result.push_back(freqVec[i].first); + } + return result; + } + + // Top K Frequent Elements using Min Heap + vector topKFrequentElementsMinHeapApproach(vector& nums, int k) { + unordered_map frequencyMap; + for (int num : nums) { + frequencyMap[num]++; + } + + priority_queue, vector>, greater>> minHeap; + for (auto& entry : frequencyMap) { + minHeap.push({entry.second, entry.first}); + if (minHeap.size() > k) { + minHeap.pop(); + } + } + + vector result; + while (!minHeap.empty()) { + result.push_back(minHeap.top().second); + minHeap.pop(); + } + return result; + } + + // K Closest Points to Origin using Max Heap + int getDistance(vector& point) { + return point[0] * point[0] + point[1] * point[1]; + } + + vector> kClosestPointsToOriginMaxHeapApproach(vector>& points, int k) { + priority_queue>> maxHeap; + for (vector& point : points) { + maxHeap.push({getDistance(point), point}); + if (maxHeap.size() > k) { + maxHeap.pop(); + } + } + + vector> result; + while (!maxHeap.empty()) { + result.push_back(maxHeap.top().second); + maxHeap.pop(); + } + return result; + } +}; \ 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/fast_and_slow_pointers.go b/patterns/go/fast_and_slow_pointers.go new file mode 100644 index 0000000..f4bb6e0 --- /dev/null +++ b/patterns/go/fast_and_slow_pointers.go @@ -0,0 +1,98 @@ +package main + +import "fmt" + +type ListNode struct { + Val int + Next *ListNode +} + +// LeetCode 141 - Linked List Cycle (HashSet Approach) +func hasCycleHashSetApproach(head *ListNode) bool { + visited := map[*ListNode]bool{} + current := head + for current != nil { + if visited[current] { + return true + } + visited[current] = true + current = current.Next + } + return false +} + +// LeetCode 141 - Linked List Cycle (Fast and Slow Pointer Approach) +func hasCycleFastAndSlowPointersApproach(head *ListNode) bool { + if head == nil || head.Next == nil { + return false + } + slow, fast := head, head + for fast != nil && fast.Next != nil { + slow = slow.Next + fast = fast.Next.Next + if slow == fast { + return true + } + } + return false +} + +// LeetCode 876 - Middle of the Linked List (Counting Approach) +func middleNodeCountingApproach(head *ListNode) *ListNode { + count := 0 + current := head + for current != nil { + count++ + current = current.Next + } + current = head + for i := 0; i < count/2; i++ { + current = current.Next + } + return current +} + +// LeetCode 876 - Middle of the Linked List (Fast and Slow Pointer Approach) +func middleNodeFastAndSlowPointerApproach(head *ListNode) *ListNode { + slow, fast := head, head + for fast != nil && fast.Next != nil { + slow = slow.Next + fast = fast.Next.Next + } + return slow +} + +// LeetCode 202 - Happy Number (HashSet Approach) +func getSumOfSquares(n int) int { + sum := 0 + for n > 0 { + digit := n % 10 + sum += digit * digit + n /= 10 + } + return sum +} + +func isHappyHashSetApproach(n int) bool { + seen := map[int]bool{} + for n != 1 && !seen[n] { + seen[n] = true + n = getSumOfSquares(n) + } + return n == 1 +} + +// LeetCode 202 - Happy Number (Fast and Slow Pointer Approach) +func isHappyFastAndSlowPointersApproach(n int) bool { + slow := n + fast := getSumOfSquares(n) + for fast != 1 && slow != fast { + slow = getSumOfSquares(slow) + fast = getSumOfSquares(getSumOfSquares(fast)) + } + return fast == 1 +} + +func main() { + // You can test the implementations here +} \ No newline at end of file diff --git a/patterns/go/kadane_algorithm.go b/patterns/go/kadane_algorithm.go new file mode 100644 index 0000000..4832097 --- /dev/null +++ b/patterns/go/kadane_algorithm.go @@ -0,0 +1,15 @@ +package main + +import "math" + +func maxSubArray(nums []int) int { + currentSum := nums[0] + maxSum := nums[0] + + for i := 1; i < len(nums); i++ { + currentSum = int(math.Max(float64(nums[i]), float64(currentSum+nums[i]))) + maxSum = int(math.Max(float64(maxSum), float64(currentSum))) + } + + return maxSum +} diff --git a/patterns/go/level_order_traversal.go b/patterns/go/level_order_traversal.go new file mode 100644 index 0000000..04e388e --- /dev/null +++ b/patterns/go/level_order_traversal.go @@ -0,0 +1,39 @@ +package main + +import "fmt" + +// Definition for a binary tree node. +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +func levelOrder(root *TreeNode) { + if root == nil { + return + } + + queue := []*TreeNode{root} + + for len(queue) > 0 { + node := queue[0] + queue = queue[1:] + fmt.Print(node.Val, " ") // Process the node by printing its value + + // Add the left and right children to the queue, if they exist + if node.Left != nil { + queue = append(queue, node.Left) + } + if node.Right != nil { + queue = append(queue, node.Right) + } +} + +func main() { + // Example usage + root := &TreeNode{Val: 1} + root.Left = &TreeNode{Val: 2} + root.Right = &TreeNode{Val: 3} + levelOrder(root) // Output: 1 2 3 +} \ 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/reverse_list.go b/patterns/go/reverse_list.go new file mode 100644 index 0000000..8cbcaed --- /dev/null +++ b/patterns/go/reverse_list.go @@ -0,0 +1,19 @@ +package main + +type ListNode struct { + Val int + Next *ListNode +} + +func reverseList(head *ListNode) *ListNode { + var prev *ListNode = nil + curr := head + + for curr != nil { + next := curr.Next + curr.Next = prev + prev = curr + curr = next + } + return prev +} 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/top_k_elements.go b/patterns/go/top_k_elements.go new file mode 100644 index 0000000..3a8d0f4 --- /dev/null +++ b/patterns/go/top_k_elements.go @@ -0,0 +1,96 @@ +package main + +import ( + "container/heap" + "sort" +) + +// ********** K Largest Elements ********** +// K Largest Elements using Sorting +func kLargestElementsSortingApproach(nums []int, k int) []int { + sort.Sort(sort.Reverse(sort.IntSlice(nums))) + return nums[:k] +} + +// K Largest Elements using Max Heap +func kLargestElementsMaxHeapApproach(nums []int, k int) []int { + h := &MaxHeap{} + heap.Init(h) + for _, num := range nums { + heap.Push(h, num) + } + result := make([]int, k) + for i := 0; i < k; i++ { + result[i] = heap.Pop(h).(int) + } + return result +} + +// K Largest Elements using Min Heap +func kLargestElementsMinHeapApproach(nums []int, k int) []int { + h := &MinHeap{} + heap.Init(h) + for i := 0; i < k; i++ { + heap.Push(h, nums[i]) + } + for i := k; i < len(nums); i++ { + heap.Push(h, nums[i]) + if h.Len() > k { + heap.Pop(h) + } + } + result := make([]int, k) + for i := 0; i < k; i++ { + result[i] = heap.Pop(h).(int) + } + return result +} + +// ********** Helper Structures ********** + +type MaxHeap []int +type MinHeap []int + +func (h MaxHeap) Len() int { return len(h) } +func (h MaxHeap) Less(i, j int) bool { return h[i] > h[j] } // Max heap +func (h MaxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *MaxHeap) Push(x interface{}) { *h = append(*h, x.(int)) } +func (h *MaxHeap) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} + +func (h MinHeap) Len() int { return len(h) } +func (h MinHeap) Less(i, j int) bool { return h[i] < h[j] } // Min heap +func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *MinHeap) Push(x interface{}) { *h = append(*h, x.(int)) } +func (h *MinHeap) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[0 : n-1] + return x +} + +// ********** Main ********** + +func main() { + // Example test cases + nums := []int{3, 2, 1, 5, 6, 4} + k := 2 + + // Sorting Approach + result := kLargestElementsSortingApproach(nums, k) + fmt.Println("K Largest Elements (Sorting Approach):", result) + + // Max Heap Approach + result = kLargestElementsMaxHeapApproach(nums, k) + fmt.Println("K Largest Elements (Max Heap Approach):", result) + + // Min Heap Approach + result = kLargestElementsMinHeapApproach(nums, k) + fmt.Println("K Largest Elements (Min Heap Approach):", result) +} \ No newline at end of file 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/FastAndSlowPointers.java b/patterns/java/FastAndSlowPointers.java new file mode 100644 index 0000000..666e433 --- /dev/null +++ b/patterns/java/FastAndSlowPointers.java @@ -0,0 +1,123 @@ +package patterns.java; + +import java.util.HashSet; + +public class FastAndSlowPointers { + + class ListNode { + int val; + ListNode next; + ListNode(int x) { + val = x; + next = null; + } + } + +/* + * ********** LeetCode 141 - Linked List Cycle (https://leetcode.com/problems/linked-list-cycle/) ********** +*/ + + public boolean hasCycleHashSetAppraoch(ListNode head) { + HashSet visited = new HashSet<>(); + ListNode current = head; + while (current != null) { + if (visited.contains(current)) { + return true; // Cycle detected + } + visited.add(current); + current = current.next; + } + return false; // No cycle + } + + public boolean hasCycleFastAndSlowPointersAppraoch(ListNode head) { + if (head == null || head.next == null) { + return false; // No cycle if the list is empty or has only one node + } + + ListNode slow = head; + ListNode fast = head; + + while (fast != null && fast.next != null) { + slow = slow.next; // Move slow pointer by 1 step + fast = fast.next.next; // Move fast pointer by 2 steps + + if (slow == fast) { + return true; // Cycle detected + } + } + + return false; // No cycle + } + +/* + * ********** LeetCode 876 - Middle of the Linked List (https://leetcode.com/problems/middle-of-the-linked-list/description/) ********** +*/ + + public ListNode middleNodeCountingApproach(ListNode head) { + int count = 0; + ListNode current = head; + + // First pass to count the number of nodes + while (current != null) { + count++; + current = current.next; + } + + // Second pass to find the middle node + current = head; + for (int i = 0; i < count / 2; i++) { + current = current.next; + } + + return current; // This will be the middle node + } + + public ListNode middleNodeFastAndSlowPointerApproach(ListNode head) { + ListNode slow = head; + ListNode fast = head; + + // Move slow by 1 and fast by 2 steps + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; // Slow will be at the middle node + } + +/* + * ********** LeetCode 202 - Happy Number (https://leetcode.com/problems/happy-number/description/) ********** +*/ + + private int getSumOfSquares(int n) { + int sum = 0; + while (n > 0) { + int digit = n % 10; + sum += digit * digit; + n /= 10; + } + return sum; + } + + public boolean isHappyHashSetApproach(int n) { + HashSet seen = new HashSet<>(); + while (n != 1 && !seen.contains(n)) { + seen.add(n); + n = getSumOfSquares(n); + } + return n == 1; + } + + public boolean isHappyFastAndSlowPointersApproach(int n) { + int slow = n; + int fast = getSumOfSquares(n); + + while (fast != 1 && slow != fast) { + slow = getSumOfSquares(slow); // Move slow by 1 step + fast = getSumOfSquares(getSumOfSquares(fast)); // Move fast by 2 steps + } + + return fast == 1; + } +} \ No newline at end of file diff --git a/patterns/java/KadaneAlgorithm.java b/patterns/java/KadaneAlgorithm.java new file mode 100644 index 0000000..9e3f46b --- /dev/null +++ b/patterns/java/KadaneAlgorithm.java @@ -0,0 +1,17 @@ +package patterns.java; + +public class KadaneAlgorithm { + public int maxSubArray(int[] 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 (int i = 1; i < nums.length; i++) { + // If currentSum is negative, reset to current element + currentSum = Math.max(nums[i], currentSum + nums[i]); + // Update maxSum if currentSum is greater + maxSum = Math.max(maxSum, currentSum); + } + return maxSum; + } +} \ No newline at end of file diff --git a/patterns/java/LevelOrderTraversal.java b/patterns/java/LevelOrderTraversal.java new file mode 100644 index 0000000..ac56f0f --- /dev/null +++ b/patterns/java/LevelOrderTraversal.java @@ -0,0 +1,33 @@ +package patterns.java; + +import java.util.LinkedList; +import java.util.Queue; + +// Definition for a binary tree node. +class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode(int x) { + val = x; + } +} + +public class LevelOrderTraversal { + public void levelOrder(TreeNode root) { + if (root == null) return; + + Queue queue = new LinkedList<>(); + queue.add(root); + + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + System.out.print(node.val + " "); // Process the node by printing its value + + // Add the left and right children to the queue, if they exist + if (node.left != null) queue.add(node.left); + if (node.right != null) queue.add(node.right); + } + } +} 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/ReverseLinkedList.java b/patterns/java/ReverseLinkedList.java new file mode 100644 index 0000000..3bd0843 --- /dev/null +++ b/patterns/java/ReverseLinkedList.java @@ -0,0 +1,20 @@ +package patterns.java; + +class ListNode { + int val; + ListNode next; +} + +public class ReverseLinkedList { + public ListNode reverseList(ListNode head) { + ListNode prev = null; // Previous node, initially null + ListNode curr = head; // Current node starts from the head + while (curr != null) { + ListNode next = curr.next; // Store next node + curr.next = prev; // Reverse the current node's pointer + prev = curr; // Move prev to current + curr = next; // Move curr to next + } + return prev; // New head of the reversed list + } +} 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 new file mode 100644 index 0000000..15946b1 --- /dev/null +++ b/patterns/java/TopKElements.java @@ -0,0 +1,151 @@ +package patterns.java; + +import patterns.java.FastAndSlowPointers.ListNode; +import java.util.*; + +public class TopKElements { + + /* + * ********** K Largest Elements ********** + */ + + public int[] kLargestElementsSortingAppraoch(int[] nums, int k) { + // Step 1: Sort the array in descending order + Integer[] numsArray = Arrays.stream(nums).boxed().toArray(Integer[]::new); + Arrays.sort(numsArray, Collections.reverseOrder()); + + // Step 2: Extract the first K elements + int[] result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = numsArray[i]; + } + return result; + } + + public int[] kLargestElementsMaxHeapAppraoch(int[] nums, int k) { + // Max heap + PriorityQueue maxHeap = new PriorityQueue<>(Collections.reverseOrder()); + + // Add all numbers to the max heap + for (int num : nums) { + maxHeap.add(num); + } + + // Extract the top K largest elements + int[] result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = maxHeap.poll(); // Extracts the largest element + } + return result; + } + + public int[] kLargestElementsMinHeapAppraoch(int[] nums, int k) { + // Min heap + PriorityQueue minHeap = new PriorityQueue<>(); + + // Add first K elements into the min heap + for(int i = 0; i < k; i++) { + minHeap.add(nums[i]); + } + + // Process the remaining elements + for (int i = k; i < nums.length; i++) { + minHeap.add(nums[i]); + if (minHeap.size() > k) { + minHeap.poll(); + } + } + + // Extract the top K largest elements from the min heap + int[] result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = minHeap.poll(); + } + return result; + } + + /* + * ********** LeetCode 347 - Top K Frequent Elements (https://leetcode.com/problems/top-k-frequent-elements/description/) ********** + */ + + public int[] topKFrequentElementsSortingApproach(int[] nums, int k) { + // Step 1: Build the frequency map + Map frequencyMap = new HashMap<>(); + for (int num : nums) { + frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1); + } + + // Step 2: Sort the entries by frequency in descending order + List> entryList = new ArrayList<>(frequencyMap.entrySet()); + entryList.sort((a, b) -> b.getValue() - a.getValue()); + + // Step 3: Extract the top K elements + int[] result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = entryList.get(i).getKey(); + } + + return result; + } + + public int[] topKFrequentElementsMinHeapApproach(int[] nums, int k) { + // Step 1: Build the frequency map + Map frequencyMap = new HashMap<>(); + for (int num : nums) { + frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1); + } + + // Step 2: Use a min heap to keep track of the top K elements + PriorityQueue> minHeap = new PriorityQueue<>( + (a, b) -> a.getValue() - b.getValue() // Compare by frequency + ); + + // Step 3: Add each entry to the heap, and maintain size K + for (Map.Entry entry : frequencyMap.entrySet()) { + minHeap.add(entry); + if (minHeap.size() > k) { + minHeap.poll(); // Remove the element with the lowest frequency + } + } + + // Step 4: Extract the elements from the heap + int[] result = new int[k]; + for (int i = 0; i < k; i++) { + result[i] = minHeap.poll().getKey(); // Get the element (key) from the heap + } + + return result; + } + + /* + * ********** LeetCode 973 - K Closest Points to Origin (https://leetcode.com/problems/k-closest-points-to-origin/description/) ********** + */ + private int getDistance(int[] point) { + return point[0] * point[0] + point[1] * point[1]; // Squared distance to avoid floating-point operations + } + + public int[][] kClosestPointsToOriginMaxHeapApproach(int[][] points, int k) { + // Max heap with custom comparator to compare by distance + PriorityQueue maxHeap = new PriorityQueue<>( + (a, b) -> Integer.compare(getDistance(b), getDistance(a)) + ); + + // Iterate through all points + for (int[] point : points) { + maxHeap.add(point); // Add the current point to the heap + + // If the heap exceeds size K, remove the farthest point + if (maxHeap.size() > k) { + maxHeap.poll(); // Remove the point with the largest distance (root of max heap) + } + } + + // Convert the remaining points in the heap to the result array + int[][] result = new int[k][2]; + for (int i = 0; i < k; i++) { + result[i] = maxHeap.poll(); + } + + return result; + } +} 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/fastAndSlowPointers.js b/patterns/javascript/fastAndSlowPointers.js new file mode 100644 index 0000000..0ddc20a --- /dev/null +++ b/patterns/javascript/fastAndSlowPointers.js @@ -0,0 +1,84 @@ +class ListNode { + constructor(x) { + this.val = x; + this.next = null; + } +} + +class FastAndSlowPointers { + // LeetCode 141 - Linked List Cycle (HashSet Approach) + hasCycleHashSetApproach(head) { + const visited = new Set(); + let current = head; + while (current) { + if (visited.has(current)) { + return true; + } + visited.add(current); + current = current.next; + } + return false; + } + + // LeetCode 141 - Linked List Cycle (Fast and Slow Pointer Approach) + hasCycleFastAndSlowPointersApproach(head) { + if (!head || !head.next) return false; + let slow = head, fast = head; + while (fast && fast.next) { + slow = slow.next; + fast = fast.next.next; + if (slow === fast) return true; + } + return false; + } + + // LeetCode 876 - Middle of the Linked List (Counting Approach) + middleNodeCountingApproach(head) { + let count = 0; + let current = head; + while (current) { + count++; + current = current.next; + } + current = head; + for (let i = 0; i < Math.floor(count / 2); i++) { + current = current.next; + } + return current; + } + + // LeetCode 876 - Middle of the Linked List (Fast and Slow Pointer Approach) + middleNodeFastAndSlowPointerApproach(head) { + let slow = head, fast = head; + while (fast && fast.next) { + slow = slow.next; + fast = fast.next.next; + } + return slow; + } + + // LeetCode 202 - Happy Number (HashSet Approach) + getSumOfSquares(n) { + return String(n).split('').reduce((sum, digit) => sum + digit * digit, 0); + } + + isHappyHashSetApproach(n) { + const seen = new Set(); + while (n !== 1 && !seen.has(n)) { + seen.add(n); + n = this.getSumOfSquares(n); + } + return n === 1; + } + + // LeetCode 202 - Happy Number (Fast and Slow Pointer Approach) + isHappyFastAndSlowPointersApproach(n) { + let slow = n; + let fast = this.getSumOfSquares(n); + while (fast !== 1 && slow !== fast) { + slow = this.getSumOfSquares(slow); + fast = this.getSumOfSquares(this.getSumOfSquares(fast)); + } + return fast === 1; + } +} \ No newline at end of file diff --git a/patterns/javascript/kadaneAlgorithm.js b/patterns/javascript/kadaneAlgorithm.js new file mode 100644 index 0000000..859b036 --- /dev/null +++ b/patterns/javascript/kadaneAlgorithm.js @@ -0,0 +1,12 @@ +class KadaneAlgorithm { + maxSubArray(nums) { + let currentSum = nums[0]; + let maxSum = nums[0]; + + for (let i = 1; i < nums.length; i++) { + currentSum = Math.max(nums[i], currentSum + nums[i]); + maxSum = Math.max(maxSum, currentSum); + } + return maxSum; + } +} \ No newline at end of file diff --git a/patterns/javascript/levelOrderTraversal.js b/patterns/javascript/levelOrderTraversal.js new file mode 100644 index 0000000..c65bab9 --- /dev/null +++ b/patterns/javascript/levelOrderTraversal.js @@ -0,0 +1,24 @@ +// Definition for a binary tree node. +class TreeNode { + constructor(val) { + this.val = val; + this.left = this.right = null; + } +} + +class LevelOrderTraversal { + levelOrder(root) { + if (root === null) return; + + const queue = [root]; + + while (queue.length > 0) { + const node = queue.shift(); + console.log(node.val); // Process the node by printing its value + + // Add the left and right children to the queue, if they exist + if (node.left !== null) queue.push(node.left); + if (node.right !== null) queue.push(node.right); + } + } +} \ 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/reverseList.js b/patterns/javascript/reverseList.js new file mode 100644 index 0000000..317f50e --- /dev/null +++ b/patterns/javascript/reverseList.js @@ -0,0 +1,19 @@ +class ListNode { + constructor(val = 0, next = null) { + this.val = val; + this.next = next; + } +} + +function reverseList(head) { + let prev = null; + let curr = head; + + while (curr !== null) { + let next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; +} \ 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/topKElements.js b/patterns/javascript/topKElements.js new file mode 100644 index 0000000..c8ab028 --- /dev/null +++ b/patterns/javascript/topKElements.js @@ -0,0 +1,88 @@ +class TopKElements { + + // K Largest Elements using Sorting + kLargestElementsSortingApproach(nums, k) { + nums.sort((a, b) => b - a); + return nums.slice(0, k); + } + + // K Largest Elements using Max Heap + kLargestElementsMaxHeapApproach(nums, k) { + const maxHeap = new MaxPriorityQueue({ priority: x => x }); + for (const num of nums) { + maxHeap.enqueue(num); + } + const result = []; + for (let i = 0; i < k; i++) { + result.push(maxHeap.dequeue().element); + } + return result; + } + + // K Largest Elements using Min Heap + kLargestElementsMinHeapApproach(nums, k) { + const minHeap = new MinPriorityQueue({ priority: x => x }); + for (let i = 0; i < k; i++) { + minHeap.enqueue(nums[i]); + } + for (let i = k; i < nums.length; i++) { + minHeap.enqueue(nums[i]); + if (minHeap.size() > k) { + minHeap.dequeue(); + } + } + const result = []; + for (let i = 0; i < k; i++) { + result.push(minHeap.dequeue().element); + } + return result; + } + + // Top K Frequent Elements using Sorting + topKFrequentElementsSortingApproach(nums, k) { + const frequencyMap = new Map(); + nums.forEach(num => frequencyMap.set(num, (frequencyMap.get(num) || 0) + 1)); + return Array.from(frequencyMap) + .sort((a, b) => b[1] - a[1]) + .slice(0, k) + .map(entry => entry[0]); + } + + // Top K Frequent Elements using Min Heap + topKFrequentElementsMinHeapApproach(nums, k) { + const frequencyMap = new Map(); + nums.forEach(num => frequencyMap.set(num, (frequencyMap.get(num) || 0) + 1)); + const minHeap = new MinPriorityQueue({ priority: x => x[1] }); + frequencyMap.forEach((value, key) => { + minHeap.enqueue([key, value]); + if (minHeap.size() > k) { + minHeap.dequeue(); + } + }); + const result = []; + for (let i = 0; i < k; i++) { + result.push(minHeap.dequeue().element[0]); + } + return result; + } + + // K Closest Points to Origin using Max Heap + getDistance(point) { + return point[0] ** 2 + point[1] ** 2; + } + + kClosestPointsToOriginMaxHeapApproach(points, k) { + const maxHeap = new MaxPriorityQueue({ priority: point => -this.getDistance(point) }); + points.forEach(point => { + maxHeap.enqueue(point); + if (maxHeap.size() > k) { + maxHeap.dequeue(); + } + }); + const result = []; + for (let i = 0; i < k; i++) { + result.push(maxHeap.dequeue().element); + } + return result; + } +} \ 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/fast_and_slow_pointers.py b/patterns/python/fast_and_slow_pointers.py new file mode 100644 index 0000000..be6ed55 --- /dev/null +++ b/patterns/python/fast_and_slow_pointers.py @@ -0,0 +1,68 @@ +class ListNode: + def __init__(self, x): + self.val = x + self.next = None + +class FastAndSlowPointers: + # LeetCode 141 - Linked List Cycle (HashSet Approach) + def hasCycleHashSetApproach(self, head): + visited = set() + current = head + while current: + if current in visited: + return True + visited.add(current) + current = current.next + return False + + # LeetCode 141 - Linked List Cycle (Fast and Slow Pointer Approach) + def hasCycleFastAndSlowPointersApproach(self, head): + if not head or not head.next: + return False + slow, fast = head, head + while fast and fast.next: + slow = slow.next + fast = fast.next.next + if slow == fast: + return True + return False + + # LeetCode 876 - Middle of the Linked List (Counting Approach) + def middleNodeCountingApproach(self, head): + count = 0 + current = head + while current: + count += 1 + current = current.next + current = head + for _ in range(count // 2): + current = current.next + return current + + # LeetCode 876 - Middle of the Linked List (Fast and Slow Pointer Approach) + def middleNodeFastAndSlowPointerApproach(self, head): + slow, fast = head, head + while fast and fast.next: + slow = slow.next + fast = fast.next.next + return slow + + # LeetCode 202 - Happy Number (HashSet Approach) + def getSumOfSquares(self, n): + return sum(int(digit)**2 for digit in str(n)) + + def isHappyHashSetApproach(self, n): + seen = set() + while n != 1 and n not in seen: + seen.add(n) + n = self.getSumOfSquares(n) + return n == 1 + + # LeetCode 202 - Happy Number (Fast and Slow Pointer Approach) + def isHappyFastAndSlowPointersApproach(self, n): + slow = n + fast = self.getSumOfSquares(n) + while fast != 1 and slow != fast: + slow = self.getSumOfSquares(slow) + fast = self.getSumOfSquares(self.getSumOfSquares(fast)) + return fast == 1 \ No newline at end of file diff --git a/patterns/python/kadane_algorithm.py b/patterns/python/kadane_algorithm.py new file mode 100644 index 0000000..66bdd33 --- /dev/null +++ b/patterns/python/kadane_algorithm.py @@ -0,0 +1,10 @@ +class KadaneAlgorithm: + def max_sub_array(self, nums): + current_sum = nums[0] + max_sum = nums[0] + + for i in range(1, len(nums)): + current_sum = max(nums[i], current_sum + nums[i]) + max_sum = max(max_sum, current_sum) + + return max_sum \ No newline at end of file diff --git a/patterns/python/level_order_traversal.py b/patterns/python/level_order_traversal.py new file mode 100644 index 0000000..c52fc99 --- /dev/null +++ b/patterns/python/level_order_traversal.py @@ -0,0 +1,25 @@ +from collections import deque + +# Definition for a binary tree node. +class TreeNode: + def __init__(self, x): + self.val = x + self.left = None + self.right = None + +class LevelOrderTraversal: + def level_order(self, root): + if root is None: + return + + queue = deque([root]) + + while queue: + node = queue.popleft() + print(node.val, end=" ") # Process the node by printing its value + + # Add the left and right children to the queue, if they exist + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) \ 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/reverse_list.py b/patterns/python/reverse_list.py new file mode 100644 index 0000000..ec842b3 --- /dev/null +++ b/patterns/python/reverse_list.py @@ -0,0 +1,16 @@ +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + +def reverse_list(head): + prev = None + curr = head + + while curr: + next_node = curr.next + curr.next = prev + prev = curr + curr = next_node + + return prev \ 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/top_k_elements.py b/patterns/python/top_k_elements.py new file mode 100644 index 0000000..cf234c1 --- /dev/null +++ b/patterns/python/top_k_elements.py @@ -0,0 +1,49 @@ +import heapq +from collections import Counter + +class TopKElements: + + # K Largest Elements using Sorting + def k_largest_elements_sorting_approach(self, nums, k): + return sorted(nums, reverse=True)[:k] + + # K Largest Elements using Max Heap + def k_largest_elements_max_heap_approach(self, nums, k): + return heapq.nlargest(k, nums) + + # K Largest Elements using Min Heap + def k_largest_elements_min_heap_approach(self, nums, k): + min_heap = nums[:k] + heapq.heapify(min_heap) + for num in nums[k:]: + heapq.heappush(min_heap, num) + if len(min_heap) > k: + heapq.heappop(min_heap) + return [heapq.heappop(min_heap) for _ in range(k)][::-1] + + # Top K Frequent Elements using Sorting + def top_k_frequent_elements_sorting_approach(self, nums, k): + count = Counter(nums) + return [num for num, freq in count.most_common(k)] + + # Top K Frequent Elements using Min Heap + def top_k_frequent_elements_min_heap_approach(self, nums, k): + count = Counter(nums) + min_heap = [] + for num, freq in count.items(): + heapq.heappush(min_heap, (freq, num)) + if len(min_heap) > k: + heapq.heappop(min_heap) + return [heapq.heappop(min_heap)[1] for _ in range(k)][::-1] + + # K Closest Points to Origin using Max Heap + def get_distance(self, point): + return point[0] ** 2 + point[1] ** 2 + + def k_closest_points_to_origin_max_heap_approach(self, points, k): + max_heap = [] + for point in points: + heapq.heappush(max_heap, (-self.get_distance(point), point)) + if len(max_heap) > k: + heapq.heappop(max_heap) + return [heapq.heappop(max_heap)[1] for _ in range(k)][::-1] \ 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/fastAndSlowPointers.ts b/patterns/typescript/fastAndSlowPointers.ts new file mode 100644 index 0000000..526baae --- /dev/null +++ b/patterns/typescript/fastAndSlowPointers.ts @@ -0,0 +1,86 @@ +class ListNode { + val: number; + next: ListNode | null = null; + constructor(x: number) { + this.val = x; + } +} + +class FastAndSlowPointers { + // LeetCode 141 - Linked List Cycle (HashSet Approach) + hasCycleHashSetApproach(head: ListNode | null): boolean { + const visited = new Set(); + let current = head; + while (current) { + if (visited.has(current)) { + return true; + } + visited.add(current); + current = current.next; + } + return false; + } + + // LeetCode 141 - Linked List Cycle (Fast and Slow Pointer Approach) + hasCycleFastAndSlowPointersApproach(head: ListNode | null): boolean { + if (!head || !head.next) return false; + let slow: ListNode | null = head; + let fast: ListNode | null = head; + while (fast && fast.next) { + slow = slow!.next; + fast = fast.next.next; + if (slow === fast) return true; + } + return false; + } + + // LeetCode 876 - Middle of the Linked List (Counting Approach) + middleNodeCountingApproach(head: ListNode | null): ListNode | null { + let count = 0; + let current = head; + while (current) { + count++; + current = current.next; + } + current = head; + for (let i = 0; i < Math.floor(count / 2); i++) { + current = current!.next; + } + return current; + } + + // LeetCode 876 - Middle of the Linked List (Fast and Slow Pointer Approach) + middleNodeFastAndSlowPointerApproach(head: ListNode | null): ListNode | null { + let slow = head, fast = head; + while (fast && fast.next) { + slow = slow!.next; + fast = fast.next.next; + } + return slow; + } + + // LeetCode 202 - Happy Number (HashSet Approach) + getSumOfSquares(n: number): number { + return String(n).split('').reduce((sum, digit) => sum + Number(digit) ** 2, 0); + } + + isHappyHashSetApproach(n: number): boolean { + const seen = new Set(); + while (n !== 1 && !seen.has(n)) { + seen.add(n); + n = this.getSumOfSquares(n); + } + return n === 1; + } + + // LeetCode 202 - Happy Number (Fast and Slow Pointer Approach) + isHappyFastAndSlowPointersApproach(n: number): boolean { + let slow = n; + let fast = this.getSumOfSquares(n); + while (fast !== 1 && slow !== fast) { + slow = this.getSumOfSquares(slow); + fast = this.getSumOfSquares(this.getSumOfSquares(fast)); + } + return fast === 1; + } +} \ No newline at end of file diff --git a/patterns/typescript/kadaneAlgorithm.ts b/patterns/typescript/kadaneAlgorithm.ts new file mode 100644 index 0000000..5b91e80 --- /dev/null +++ b/patterns/typescript/kadaneAlgorithm.ts @@ -0,0 +1,12 @@ +class KadaneAlgorithm { + maxSubArray(nums: number[]): number { + let currentSum: number = nums[0]; + let maxSum: number = nums[0]; + + for (let i = 1; i < nums.length; i++) { + currentSum = Math.max(nums[i], currentSum + nums[i]); + maxSum = Math.max(maxSum, currentSum); + } + return maxSum; + } +} \ No newline at end of file diff --git a/patterns/typescript/levelOrderTraversal.ts b/patterns/typescript/levelOrderTraversal.ts new file mode 100644 index 0000000..dfbbcb3 --- /dev/null +++ b/patterns/typescript/levelOrderTraversal.ts @@ -0,0 +1,28 @@ +// Definition for a binary tree node. +class BinaryTreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + + constructor(val: number) { + this.val = val; + this.left = this.right = null; + } +} + +class BinaryTreeLevelOrderTraversal { + levelOrder(root: BinaryTreeNode | null): void { + if (root === null) return; + + const queue: BinaryTreeNode[] = [root]; + + while (queue.length > 0) { + const node = queue.shift()!; + console.log(node.val); // Process the node by printing its value + + // Add the left and right children to the queue, if they exist + if (node.left !== null) queue.push(node.left); + if (node.right !== null) queue.push(node.right); + } + } +} \ 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/reverseList.ts b/patterns/typescript/reverseList.ts new file mode 100644 index 0000000..d757f7e --- /dev/null +++ b/patterns/typescript/reverseList.ts @@ -0,0 +1,22 @@ +class ListNode { + val: number; + next: ListNode | null; + + constructor(val: number = 0, next: ListNode | null = null) { + this.val = val; + this.next = next; + } +} + +function reverseList(head: ListNode | null): ListNode | null { + let prev: ListNode | null = null; + let curr: ListNode | null = head; + + while (curr !== null) { + let next: ListNode | null = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; +} \ 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/topKElements.ts b/patterns/typescript/topKElements.ts new file mode 100644 index 0000000..32ff24e --- /dev/null +++ b/patterns/typescript/topKElements.ts @@ -0,0 +1,88 @@ +class TopKElements { + + // K Largest Elements using Sorting + kLargestElementsSortingApproach(nums: number[], k: number): number[] { + nums.sort((a, b) => b - a); + return nums.slice(0, k); + } + + // K Largest Elements using Max Heap + kLargestElementsMaxHeapApproach(nums: number[], k: number): number[] { + const maxHeap = new MaxPriorityQueue({ priority: (x: number) => x }); + for (const num of nums) { + maxHeap.enqueue(num); + } + const result: number[] = []; + for (let i = 0; i < k; i++) { + result.push(maxHeap.dequeue().element); + } + return result; + } + + // K Largest Elements using Min Heap + kLargestElementsMinHeapApproach(nums: number[], k: number): number[] { + const minHeap = new MinPriorityQueue({ priority: (x: number) => x }); + for (let i = 0; i < k; i++) { + minHeap.enqueue(nums[i]); + } + for (let i = k; i < nums.length; i++) { + minHeap.enqueue(nums[i]); + if (minHeap.size() > k) { + minHeap.dequeue(); + } + } + const result: number[] = []; + for (let i = 0; i < k; i++) { + result.push(minHeap.dequeue().element); + } + return result; + } + + // Top K Frequent Elements using Sorting + topKFrequentElementsSortingApproach(nums: number[], k: number): number[] { + const frequencyMap = new Map(); + nums.forEach(num => frequencyMap.set(num, (frequencyMap.get(num) || 0) + 1)); + return Array.from(frequencyMap) + .sort((a, b) => b[1] - a[1]) + .slice(0, k) + .map(entry => entry[0]); + } + + // Top K Frequent Elements using Min Heap + topKFrequentElementsMinHeapApproach(nums: number[], k: number): number[] { + const frequencyMap = new Map(); + nums.forEach(num => frequencyMap.set(num, (frequencyMap.get(num) || 0) + 1)); + const minHeap = new MinPriorityQueue({ priority: (x: [number, number]) => x[1] }); + frequencyMap.forEach((value, key) => { + minHeap.enqueue([key, value]); + if (minHeap.size() > k) { + minHeap.dequeue(); + } + }); + const result: number[] = []; + for (let i = 0; i < k; i++) { + result.push(minHeap.dequeue().element[0]); + } + return result; + } + + // K Closest Points to Origin using Max Heap + getDistance(point: number[]): number { + return point[0] ** 2 + point[1] ** 2; + } + + kClosestPointsToOriginMaxHeapApproach(points: number[][], k: number): number[][] { + const maxHeap = new MaxPriorityQueue({ priority: (point: number[]) => -this.getDistance(point) }); + points.forEach(point => { + maxHeap.enqueue(point); + if (maxHeap.size() > k) { + maxHeap.dequeue(); + } + }); + const result: number[][] = []; + for (let i = 0; i < k; i++) { + result.push(maxHeap.dequeue().element); + } + return result; + } +} \ 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