.
================================================
FILE: README.md
================================================
Join Free Newsletter
This repository contains awesome LeetCode resources to learn Data Structures and Algorithms (DSA) and prepare for Coding interviews.
👉 If you want to master DSA 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/)
- [Arrays](https://www.youtube.com/watch?v=SlNq09scdWE&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Bit Manipulation Techniques](https://blog.algomaster.io/p/c650df76-f978-46ee-a572-eb13c354905d)
- [Sorting Algorithms](https://medium.com/jl-codes/understanding-sorting-algorithms-af6222995c8)
- [Linked List](https://www.youtube.com/watch?v=FbHf0ii0WDg&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Queues](https://medium.com/basecs/to-queue-or-not-to-queue-2653bcde5b04)
- [Stacks](https://medium.com/basecs/stacks-and-overflows-dbcf7854dc67)
- [Hash Tables](https://medium.com/basecs/taking-hash-tables-off-the-shelf-139cbf4752f0)
- [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://www.youtube.com/watch?v=xN5VGzK9_FQ&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Master Graph Algorithms](https://blog.algomaster.io/p/master-graph-algorithms-for-coding)
- [DFS Traversal](https://medium.com/basecs/deep-dive-through-a-graph-dfs-traversal-8177df5d0f13)
- [BFS Traversal](https://medium.com/basecs/going-broad-in-a-graph-bfs-traversal-959bd1a09255)
- [Union-Find](https://leetcode.com/discuss/general-discussion/1072418/Disjoint-Set-Union-(DSU)Union-Find-A-Complete-Guide)
- [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
- [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&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Sliding Window Pattern](https://www.youtube.com/watch?v=y2d0VHdvfdc&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Prefix Sum Pattern](https://www.youtube.com/watch?v=yuws7YK0Yng&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Fast and Slow Pointers Pattern](https://www.youtube.com/watch?v=b139yf7Ik-E&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Top 'K' Elements Pattern](https://www.youtube.com/watch?v=6_v6OoxvMOE&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Kadane's Algorithm](https://www.youtube.com/watch?v=NUWAXbSlsws&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Linked List In-place Reversal Pattern](https://www.youtube.com/watch?v=auoTGovuo9A&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Monotonic Stack Pattern](https://www.youtube.com/watch?v=DtJVwbbicjQ&list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2)
- [Overlapping Intervals Pattern](https://blog.algomaster.io/p/812e72f7-eced-4256-a4c1-00606ae50679)
- [Backtracking Pattern](https://blog.algomaster.io/p/81d42ca2-600c-4252-aa33-a56462090048)
- [Modified Binary Search Pattern](https://blog.algomaster.io/p/d0d81b04-4c2a-4b45-a101-5137c3146686)
- [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)
- [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)
## 📝 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
- [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/)
## 📺 YouTube Playlist
- [AlgoMaster DSA Playlist](https://www.youtube.com/playlist?list=PLK63NuByH5o9odyBT7nfYkHZyvGQ5oVp2&pp=gAQB)
- [AlgoMaster LeetCode Pattern Playlist](https://www.youtube.com/playlist?list=PLK63NuByH5o-tqaMUHRA4r8ObRW7PWz45)
- [Abdul Bari's Algorithms Playlist](https://www.youtube.com/playlist?list=PLDN4rrl48XKpZkf03iYFl-O29szjTrs_O)
- [William Fiset's Data Structure Playlist](https://www.youtube.com/playlist?list=PLDV1Zeh2NRsB6SWUrDFW2RmDotAfPbeHu)
- [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
- [Coursera - Algorithms, Part I](https://www.coursera.org/learn/algorithms-part1)
- [Coursera - Algorithms, Part 2](https://www.coursera.org/learn/algorithms-part2)
## 📚 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
- [AlgoMaster DSA Animations](https://algomaster.io/animations/dsa)
- [VisuAlgo](https://visualgo.net/en)
## 📎 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!
================================================
FILE: patterns/c#/FastAndSlowPointers.cs
================================================
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;
}
}
================================================
FILE: patterns/c#/KadaneAlgorithm.cs
================================================
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;
}
}
================================================
FILE: patterns/c#/LevelOrderTraversal.cs
================================================
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);
}
}
}
================================================
FILE: patterns/c#/MonotonicStack.cs
================================================
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;
}
}
================================================
FILE: patterns/c#/ReverseList.cs
================================================
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;
}
}
================================================
FILE: patterns/c#/SlidingWindow.cs
================================================
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;
}
}
================================================
FILE: patterns/c#/TopKElements.cs
================================================
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;
}
}
================================================
FILE: patterns/c#/TwoPointers.cs
================================================
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;
}
}
================================================
FILE: patterns/c++/FastAndSlowPointers.cpp
================================================
#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;
}
};
================================================
FILE: patterns/c++/KadaneAlgorithm.cpp
================================================
#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;
}
};
================================================
FILE: patterns/c++/LevelOrderTraversal.cpp
================================================
#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);
}
}
};
================================================
FILE: patterns/c++/MonotonicStack.cpp
================================================
#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;
}
};
================================================
FILE: patterns/c++/ReverseList.cpp
================================================
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;
}
================================================
FILE: patterns/c++/SlidingWindow.cpp
================================================
#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;
}
};
================================================
FILE: patterns/c++/TopKElements.cpp
================================================
#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;
}
};
================================================
FILE: patterns/c++/TwoPointers.cpp
================================================
#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;
}
};
================================================
FILE: patterns/go/fast_and_slow_pointers.go
================================================
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
}
================================================
FILE: patterns/go/kadane_algorithm.go
================================================
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
}
================================================
FILE: patterns/go/level_order_traversal.go
================================================
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
}
================================================
FILE: patterns/go/monotonic_stack.go
================================================
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))
}
================================================
FILE: patterns/go/reverse_list.go
================================================
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
}
================================================
FILE: patterns/go/sliding_window.go
================================================
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
}
================================================
FILE: patterns/go/top_k_elements.go
================================================
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)
}
================================================
FILE: patterns/go/two_pointers.go
================================================
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
}
================================================
FILE: patterns/java/FastAndSlowPointers.java
================================================
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;
}
}
================================================
FILE: patterns/java/KadaneAlgorithm.java
================================================
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;
}
}
================================================
FILE: patterns/java/LevelOrderTraversal.java
================================================
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);
}
}
}
================================================
FILE: patterns/java/MonotonicStack.java
================================================
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
}
}
================================================
FILE: patterns/java/ReverseLinkedList.java
================================================
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
}
}
================================================
FILE: patterns/java/SlidingWindow.java
================================================
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;
}
}
================================================
FILE: patterns/java/TopKElements.java
================================================
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;
}
}
================================================
FILE: patterns/java/TwoPointers.java
================================================
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;
}
}
================================================
FILE: patterns/javascript/fastAndSlowPointers.js
================================================
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;
}
}
================================================
FILE: patterns/javascript/kadaneAlgorithm.js
================================================
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;
}
}
================================================
FILE: patterns/javascript/levelOrderTraversal.js
================================================
// 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);
}
}
}
================================================
FILE: patterns/javascript/monotonicStack.js
================================================
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;
}
}
================================================
FILE: patterns/javascript/reverseList.js
================================================
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;
}
================================================
FILE: patterns/javascript/slidingWindow.js
================================================
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;
}
}
================================================
FILE: patterns/javascript/topKElements.js
================================================
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;
}
}
================================================
FILE: patterns/javascript/twoPointers.js
================================================
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;
}
}
================================================
FILE: patterns/python/fast_and_slow_pointers.py
================================================
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
================================================
FILE: patterns/python/kadane_algorithm.py
================================================
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
================================================
FILE: patterns/python/level_order_traversal.py
================================================
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)
================================================
FILE: patterns/python/monotonic_stack.py
================================================
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
================================================
FILE: patterns/python/reverse_list.py
================================================
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
================================================
FILE: patterns/python/sliding_window.py
================================================
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
================================================
FILE: patterns/python/top_k_elements.py
================================================
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]
================================================
FILE: patterns/python/two_pointers.py
================================================
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
================================================
FILE: patterns/typescript/fastAndSlowPointers.ts
================================================
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;
}
}
================================================
FILE: patterns/typescript/kadaneAlgorithm.ts
================================================
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;
}
}
================================================
FILE: patterns/typescript/levelOrderTraversal.ts
================================================
// 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);
}
}
}
================================================
FILE: patterns/typescript/monotonicStack.ts
================================================
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;
}
}
================================================
FILE: patterns/typescript/reverseList.ts
================================================
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;
}
================================================
FILE: patterns/typescript/slidingWindow.ts
================================================
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;
}
}
================================================
FILE: patterns/typescript/topKElements.ts
================================================
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;
}
}
================================================
FILE: patterns/typescript/twoPointers.ts
================================================
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;
}
}