[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-83298":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":13,"contributorsCount":13,"subscribersCount":13,"size":13,"stars1d":13,"stars7d":15,"stars30d":15,"stars90d":13,"forks30d":13,"starsTrendScore":13,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":17,"fork":17,"defaultBranch":18,"hasWiki":19,"hasPages":17,"topics":20,"createdAt":10,"pushedAt":10,"updatedAt":21,"readmeContent":22,"aiSummary":10,"trendingCount":13,"starSnapshotCount":13,"syncStatus":23,"lastSyncTime":24,"discoverSource":25},83298,"VCE_Hyd","Shivambansal96\u002FVCE_Hyd","Shivambansal96","This Repo is for 4th Year Sem 1 Students","https:\u002F\u002Fvardhaman.campustrack.in\u002Flab-details",null,"Java",64,0,63,1,37.6,false,"main",true,[],"2026-06-13 04:01:36","\u003Cdiv align=\"center\">\n\n# 🚀 Vardhaman College of Engineering \n\n![Java](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FJava-DSA-ED8B00?style=flat-square&logo=java)\n![Level](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLevel-Intermediate-yellow?style=flat-square)\n![Course](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FCourse-VCE%204th%20Yr%20Sem%201-blue?style=flat-square)\n![Days](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDuration-12%20Days-brightgreen?style=flat-square)\n![Status](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FStatus-In%20Progress%20🔄-orange?style=flat-square)\n\n\n\n### 🚀 *Welcome to the 12-day journey of mastering Data Structures & Algorithms in Java!* 🎯\n\n\n**Resource Link - \u003Ca href=\"https:\u002F\u002Fcanva.link\u002Fdkoxwclci31dz0q\" target=\"_blank\"  style=\"text-decoration: none\">👋 Click Me\u003C\u002Fa>**\n\n\n\nThis repository is your complete companion for understanding how data is organized, how algorithms manipulate it, and why this matters in real-world software engineering. By the end of Day 12, you'll have hands-on experience with the most fundamental DSA concepts that form the backbone of technical interviews and efficient software design.\n\n---\n\u003C\u002Fdiv>\n\n## 📚 Quick Navigation\n\n| Status | Day | Topic | Difficulty | File |\n|--------|-----|-------|-----------|------|\n| 🔴 Done | **Day 1** | [Singly Linked List](#day-1-singly-linked-list) | 🟢 Easy | `Day1LL.java` |\n| 🔴 Done | **Day 2A** | [Doubly Linked List](#day-2-doubly--circular-linked-lists) | 🟡 Medium | `Day2DLL.java` |\n| 🔴 Done | **Day 2B** | [Circular Linked List](#day-2-doubly--circular-linked-lists) | 🟡 Medium | `Day2CLL.java` |\n| 🔴 Done | **Day 3** | [Collections Framework](#day-3-collections-framework) | 🟡 Medium | `Day3Collections.java` |\n| 🔴 Done | **Day 4** | [Stacks](#day-4-stacks) | 🟡 Medium | `Day4Stacks.java` |\n| 🔴 Done | **Day 5** | [Stack Applications & Queues](#day-5-stack-applications--queues) | 🔴 Hard | `Day5Queues.java` |\n| 🔴 Done | **Day 6** | [Two Pointers](#day-6-two-pointers) | 🟡 Medium | `Day6TwoPointers.java` |\n| ⚪ Coming | **Day 7** | [Recursion & Backtracking](#day-7-recursion--backTracking) | 🟡 Medium | `Day7Recursion.java` |\n| ⚪ Coming | **Day 8-10** | [Trees & BST](#day-8-10-trees--binary-search-trees) | 🔴 Hard | `Day8Tree.java` |\n| ⚪ Coming | **Day 11-12** | [Graphs](#day-11-12-graphs) | 🔴 Hard | `Day11Graph.java` |\n\n---\n\n## 🎯 Course Overview\n\n### Learning Objectives\n\nBy the end of this 12-day intensive, you will be able to:\n\n✅ **Understand Data Organization**: Master how different data structures store and organize information  \n✅ **Analyze Performance**: Calculate and compare time & space complexity using Big O notation  \n✅ **Implement from Scratch**: Build each data structure from the ground up using Java  \n✅ **Solve Real Problems**: Apply DSA concepts to solve algorithmic challenges  \n✅ **Ace Interviews**: Be confident in coding interviews that test DSA knowledge  \n✅ **Write Efficient Code**: Optimize solutions for performance and memory usage  \n\n### Prerequisites\n\n- ✨ Solid understanding of **Java fundamentals** (variables, loops, conditionals, OOP basics)\n- ✨ Comfort with **classes and objects**\n- ✨ Basic understanding of **recursion** (will refresh if needed)\n- ✨ Logical thinking & problem-solving mindset 🧠\n\n### 12-Day Syllabus at a Glance\n\n```\nWEEK 1                          WEEK 2                           WEEK 3\nDay 1: Singly LL       ├──────► Day 4: Stacks         ├──────► Day 8: Trees\nDay 2: Doubly\u002FCirc LL  ├──────► Day 5: Stack Apps    │         Day 9: BST\nDay 3: Collections     ├──────► Day 6: Queues        │         Day 10: Tree Traversals\nDay 4: Stacks          └──────► Day 7: Deque & PQ    └──────► Day 11-12: Graphs & DP\n```\n\n---\n\n## 📖 How to Use This Repository\n\n1. **Read the Day's Module** → Start with the \"What You'll Learn\" section\n2. **Study Concepts & Diagrams** → Visual understanding comes first\n3. **Review Code Snippets** → See actual Java implementations\n4. **Open the Source File** → Examine `DayX.java` in detail\n5. **Practice Problems** → Solve the provided exercises (start with 🟢 Easy)\n6. **Check Resources** → Use external visualizers to reinforce learning\n7. **Identify Pitfalls** → Learn what *not* to do from the \"Common Mistakes\" section\n\n---\n\n# 📚 Day-by-Day Learning Modules\n\n---\n\n## Day 1: Singly Linked List\n\n**Status**: 🔴 **COMPLETED** | **Difficulty**: 🟢 **Easy** | **File**: `Day1LL.java`\n\n### 🎯 What You'll Learn\n- Create and manipulate a **singly linked list** (SLL)\n- Implement **prepend** (add at beginning) and **append** (add at end) operations\n- Navigate through linked lists using **node pointers**\n- Compare arrays vs. linked lists: when to use which?\n- Master the fundamentals that all other linked structures build upon\n\n### 📚 Concepts Explained\n\n#### What is a Singly Linked List?\n\nA **Singly Linked List (SLL)** is a linear data structure where each element (called a **Node**) contains:\n- **Data**: The actual value stored\n- **Next Pointer**: A reference to the next node in the sequence\n\n```\n┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌──────┐\n│ Data | Next │───►│ Data | Next │───►│ Data | Next │───►│ NULL │\n└─────────────┘    └─────────────┘    └─────────────┘    └──────┘\n   Node 1             Node 2             Node 3          End Marker\n```\n\n**Key Characteristics:**\n- 🔗 Unidirectional traversal (head → tail only)\n- 💾 Dynamic size (grows\u002Fshrinks as needed)\n- ⚡ No random access (must traverse from head)\n- 🧠 Each node \"remembers\" only the next node\n\n---\n\n### 💻 Key Code Snippets\n\n#### Node Class\n```java\npublic static class Node {\n    int data;\n    Node next = null;\n    \n    Node(int data) {\n        this.data = data;\n    }\n}\n```\n\n#### Append Operation\n```java\npublic void append(int data) {\n    \u002F\u002F Time Complexity: O(n) - must traverse to end\n    \u002F\u002F Space Complexity: O(1) - only create one new node\n    \n    Node newNode = new Node(data);\n    \n    if (head == null) {\n        head = newNode;\n    } else {\n        Node current = head;\n        while (current.next != null) {\n            current = current.next;  \u002F\u002F Traverse to the end\n        }\n        current.next = newNode;  \u002F\u002F Link the new node\n    }\n}\n```\n\n#### Prepend Operation\n```java\npublic void prepend(int data) {\n    \u002F\u002F Time Complexity: O(1) - constant time!\n    \u002F\u002F Space Complexity: O(1)\n    \n    Node newNode = new Node(data);\n    \n    if (head == null) {\n        head = newNode;\n    } else {\n        newNode.next = head;  \u002F\u002F New node points to current head\n        head = newNode;        \u002F\u002F New node becomes the head\n    }\n}\n```\n\n---\n\n### 🔢 Complexity Analysis\n\n| Operation | Time Complexity | Space Complexity | Notes |\n|-----------|-----------------|------------------|-------|\n| **Prepend** | O(1) | O(1) | ⚡ Super fast! Add at front |\n| **Append** | O(n) | O(1) | Slow on large lists (must find tail) |\n| **Search** | O(n) | O(1) | Must check each node |\n| **Delete** | O(n) | O(1) | Find + remove |\n| **Access** | O(n) | O(1) | No random access 😞 |\n\n---\n\n### 🎨 Visual Examples\n\n**Example: Building a list [10 → 20 → 30]**\n\n```\nStep 1: Create head = 10\n┌──────────┐\n│ 10 | ●───┼──► NULL\n└──────────┘\n\nStep 2: Append 20\n┌──────────┐    ┌──────────┐\n│ 10 | ●───┼──►│ 20 | ●───┼──► NULL\n└──────────┘    └──────────┘\n\nStep 3: Append 30\n┌──────────┐    ┌──────────┐    ┌──────────┐\n│ 10 | ●───┼──►│ 20 | ●───┼──►│ 30 | ●───┼──► NULL\n└──────────┘    └──────────┘    └──────────┘\n```\n\n---\n\n### 🧪 Practice Problems\n\n**🟢 Easy**\n1. Create a singly linked list and insert 5 numbers using prepend\u002Fappend\n2. Print all elements in the list\n3. Find the largest element in the list\n\n**🟡 Medium**\n4. Delete the middle element from a singly linked list\n5. Reverse a singly linked list\n6. Detect if there's a cycle in the list\n\n**🔴 Hard**\n7. Remove duplicates from an unsorted linked list\n8. Find the intersection point of two linked lists\n\n---\n\n### ⚠️ Common Mistakes\n\n| ❌ Mistake | ✅ Solution | 💭 Why It Matters |\n|-----------|-----------|-----------------|\n| Forgetting to update `head` when prepending | Always do `head = newNode` after linking | Otherwise, your list never changes! |\n| Infinite loop in append | Use `while (current.next != null)` not `while (current != null)` | Prevents accessing null pointer |\n| Not checking if `head == null` | Always handle empty list case first | Null pointer exception otherwise |\n| Creating new nodes unnecessarily | Only create when actually adding elements | Wastes memory |\n\n---\n\n### 🔗 External Resources\n\n- 📺 **VisuAlgo**: [Visualize Linked Lists in Action](https:\u002F\u002Fvisualgo.net\u002Fen\u002Flist)\n- 📖 **GeeksforGeeks**: [Singly Linked List Implementation](https:\u002F\u002Fwww.geeksforgeeks.org\u002Fdata-structures\u002Flinked-list\u002Fsingly-linked-list\u002F)\n- 💡 **YouTube**: \"Linked Lists Explained\" - Abdul Bari\n\n---\n\n### 📌 Key Takeaways\n\n💡 **SLL is the foundation** for understanding all linked structures  \n💡 **Prepend is O(1), Append is O(n)** - design accordingly  \n💡 **Node pointers are everything** - master the \"next\" reference  \n💡 **No random access** - is a trade-off for efficient insertion\u002Fdeletion  \n\n---\n\n## Day 2: Doubly & Circular Linked Lists\n\n**Status**: 🔴 **COMPLETED** | **Difficulty**: 🟡 **Medium** | **File**: `Day2DLL.java`\n\n### 🎯 What You'll Learn\n- Extend SLL with **bidirectional traversal** (Doubly Linked List)\n- Implement **Circular Linked List** where tail loops back to head\n- Master **two-pointer navigation** (previous & next)\n- Understand trade-offs: more flexibility vs. more complexity\n- Handle edge cases specific to doubly-linked structures\n\n### 📚 Concepts Explained\n\n#### Doubly Linked List (DLL)\n\nEach node has TWO pointers:\n\n```\n   ┌─────────────────────────────────┐\n   │                                 │\n┌──┴──┐    ┌──────────┐    ┌──────────┐\n│◄────┼───►│◄─ DLL ──►│◄───┼─────────►│\n└─────┘    └──────────┘    └──────────┘\nPrev|Next   Prev|Next       Prev|Next\n Node 1      Node 2          Node 3\n\nForward:  Node1 → Node2 → Node3\nBackward: Node1 ← Node2 ← Node3\n```\n\n**Advantages over SLL:**\n- ✅ Traverse both directions (forward & backward)\n- ✅ Delete a node if you have its reference (don't need previous)\n- ✅ Insert before a node (easier operations)\n\n**Disadvantages:**\n- ❌ Extra memory (two pointers per node)\n- ❌ More complex code (maintain both pointers)\n\n---\n\n#### Circular Linked List (CLL)\n\nThe tail's `next` pointer points **back to head** (no NULL):\n\n```\n         ┌──► Tail = NULL doesn't exist!\n         │\n    ┌────▼────┐    ┌────────┐    ┌────────┐\n    │   10    │───►│   20   │───►│   30   │\n    └────▲────┘    └────────┘    └────────┘\n         │                             │\n         └─────────────────────────────┘\n```\n\n**Use Cases:**\n- 🎮 Round-robin scheduling\n- 💿 Album playlists (next song after last = first)\n- 🕐 Clock\u002Ftimer implementations\n\n---\n\n### 💻 Key Code Snippets\n\n#### Doubly Linked List Node\n```java\nclass Node {\n    int data;\n    Node prev = null;   \u002F\u002F 👈 New! Previous node pointer\n    Node next = null;\n    \n    Node(int data) {\n        this.data = data;\n    }\n}\n```\n\n#### DLL Prepend\n```java\npublic void prepend(int data) {\n    \u002F\u002F Time: O(1) | Space: O(1)\n    \n    Node newNode = new Node(data);\n    length++;\n    \n    if (head == null) {\n        head = newNode;\n        tail = newNode;\n    } else {\n        newNode.next = head;\n        head.prev = newNode;  \u002F\u002F ← Link previous pointer\n        head = newNode;\n    }\n}\n```\n\n#### DLL Append\n```java\npublic void append(int data) {\n    \u002F\u002F Time: O(1) | Space: O(1)\n    \u002F\u002F ⚡ FASTER than SLL! Because we track tail\n    \n    Node newNode = new Node(data);\n    length++;\n    \n    if (head == null) {\n        head = newNode;\n        tail = newNode;\n    } else {\n        tail.next = newNode;\n        newNode.prev = tail;  \u002F\u002F ← Link both directions\n        tail = newNode;        \u002F\u002F Update tail\n    }\n}\n```\n\n---\n\n### 🔢 Complexity Comparison\n\n| Operation | SLL | DLL | CLL | Notes |\n|-----------|-----|-----|-----|-------|\n| **Prepend** | O(1) | O(1) | O(1) | All same |\n| **Append** | O(n) | O(1) ⚡ | O(1) ⚡ | DLL\u002FCLL better with tail tracker |\n| **Delete (with ref)** | O(n) | O(1) ⚡ | O(1) ⚡ | DLL advantage! |\n| **Backward Traverse** | ❌ N\u002FA | O(n) | O(n) | DLL\u002FCLL feature |\n| **Space\u002FNode** | 1 pointer | 2 pointers | 1 pointer | DLL uses more memory |\n\n---\n\n### 🎨 Visual Walkthrough\n\n**Building a DLL: [5 → 10 → 15]**\n\n```\nPrepend 5:        Append 10:         Append 15:\n┌────────┐       ┌────────┐         ┌────────┐    ┌────────┐    ┌────────┐\n│ 5|●|● │       │ 5|●|●──┼────────►│ 5|●|●──┼───►│10|●|●  │   │15|●|●  │\n└────────┘       └────────┘         └────────┘    └────────┘    └────────┘\n                                                        ▲            │\n                                                        └────────────┘\n                                                   (Backward links)\n```\n\n**Circular List: [A → B → C → A → ...]**\n\n```\n         ┌────────────────┐\n         │                │\n    ┌────▼────┐    ┌─────▼──┐    ┌─────────┐\n    │    A    │───►│   B    │───►│    C    │\n    └─────────┘    └────────┘    └────▲────┘\n         ▲                              │\n         └──────────────────────────────┘\n    Tail.next = Head (creates the circle)\n```\n\n---\n\n### 🧪 Practice Problems\n\n**🟢 Easy**\n1. Display DLL elements forward and backward\n2. Create a circular linked list and traverse it\n3. Count total nodes in a DLL\n\n**🟡 Medium**\n4. Delete a node at a specific position in DLL\n5. Insert a node after a given value in DLL\n6. Check if a circular list has a cycle\n\n**🔴 Hard**\n7. Reverse a doubly linked list\n8. Find pairs in a DLL that sum to a given value\n9. Implement sorted insertion in a DLL\n\n---\n\n### ⚠️ Common Mistakes\n\n| ❌ Mistake | ✅ Solution |\n|-----------|-----------|\n| Forgetting to update `prev` pointers | After linking `next`, also link `prev` |\n| Using DLL when SLL suffices | Extra memory overhead; only use if you need backward traversal |\n| Not tracking `tail` in DLL | Append becomes O(n) instead of O(1) |\n| Infinite loops in circular lists | Must track visited nodes or use length counter |\n| Not handling NULL properly in CLL | Remember: no node's next is NULL (except error cases) |\n\n---\n\n### 🔗 External Resources\n\n- 📺 **VisuAlgo - Linked List**: [Doubly & Circular LL Visualization](https:\u002F\u002Fvisualgo.net\u002Fen\u002Flist)\n- 📖 **LeetCode**: Practice problems on linked lists (filter by easy\u002Fmedium)\n- 🎥 **YouTube**: \"Doubly Linked Lists Explained\" - Code Help\n\n---\n\n### 📌 Key Takeaways\n\n💡 **DLL = SLL + Backward Navigation** at the cost of extra memory  \n💡 **Always track tail** in DLL\u002FCLL for O(1) append  \n💡 **Circular lists loop forever** - be careful with traversal  \n💡 **Trade-off thinking**: Extra pointers = More flexibility but more complexity  \n\n---\n\n## Day 3: Collections Framework\n\n**Status**: 🔴 **COMPLETED** | **Difficulty**: 🟡 **Medium** | **File**: `Day3Collections.java`\n\n### 🎯 What You'll Learn\n- Master the **Collections Framework hierarchy**: Iterable → Collection → Specific types\n- Understand and implement **Lists** (ArrayList, LinkedList, Stack)\n- Work with **Sets** (HashSet, TreeSet, LinkedHashSet)\n- Implement **Queues** (Queue, ArrayDeque, PriorityQueue)\n- Use **Iterators** for traversing collections safely\n- Create **custom Comparators** for sorting (Lambda & Non-Lambda expressions)\n- Apply collections to solve real problems (duplicates, k-largest elements)\n\n### 📚 Concepts Explained\n\n#### Collections Framework Hierarchy\n\n```\nIterable (Top Level)\n    │\n    └─► Collection (Interface)\n        │\n        ├─► List (Ordered, allows duplicates)\n        │   ├─ ArrayList (Dynamic array-based)\n        │   ├─ LinkedList (Node-based)\n        │   └─ Stack (LIFO)\n        │\n        ├─► Set (Unique elements only)\n        │   ├─ HashSet (Randomized order, O(1) lookup)\n        │   ├─ TreeSet (Sorted order, O(log n) lookup)\n        │   └─ LinkedHashSet (Insertion order)\n        │\n        └─► Queue (FIFO)\n            ├─ LinkedList (Standard queue)\n            ├─ ArrayDeque (Double-ended queue)\n            └─ PriorityQueue (Min-heap by default)\n```\n\n#### Key Interfaces\n\n**Iterable**: Allows use of enhanced for-loop and Iterator\n```\nIterable → hasNext() \u002F next() → iterate safely\n```\n\n**Collection**: Common methods for all collections\n```\nadd(), remove(), contains(), size(), isEmpty(), clear()\n```\n\n#### Lists - Ordered Collections\n\n| Type | Implementation | Time: Add\u002FRemove\u002FGet | Order | Use Case |\n|------|-----------------|----------------------|-------|----------|\n| **ArrayList** | Dynamic array | O(1) add end, O(n) middle | Insertion | Fast access, frequent reads |\n| **LinkedList** | Doubly-linked | O(1) add\u002Fremove at ends, O(n) middle | Insertion | Frequent inserts\u002Fdeletes |\n| **Stack** | LIFO | O(1) push\u002Fpop | LIFO | Undo, recursion, parsing |\n\n#### Sets - Unique Elements\n\n| Type | Implementation | Time: Add\u002FRemove\u002FLookup | Order | Use Case |\n|------|-----------------|------------------------|-------|----------|\n| **HashSet** | Hash table | O(1) average | Random | Fast duplicate detection |\n| **TreeSet** | Red-Black Tree | O(log n) | Sorted | Sorted unique values |\n| **LinkedHashSet** | Hash + LinkedList | O(1) average | Insertion | Maintain order, unique values |\n\n#### Queues - FIFO Collections\n\n| Type | Operations | Special Features | Use Case |\n|------|-----------|-----------------|----------|\n| **LinkedList Queue** | offer\u002Fpoll\u002Fpeek | Standard FIFO | Basic queueing |\n| **ArrayDeque** | offerFirst\u002FofferLast\u002FpollFirst\u002FpollLast | Deque (both ends) | Efficient double-ended ops |\n| **PriorityQueue** | offer\u002Fpoll\u002Fpeek | Min-heap by default | Scheduling, k-largest |\n\n---\n\n### 💻 Key Code Snippets\n\n#### Comparator with Lambda Expression\n```java\n\u002F\u002F Sorting by last digit of numbers\nList\u003CInteger> arrList = new ArrayList\u003C>(Arrays.asList(22, 33, 41, 55, 69, 90));\n\nComparator\u003CInteger> comp = (Integer a, Integer b) -> {\n    if (a % 10 > b % 10) {\n        return 1;    \u002F\u002F a should come after b (ascending by last digit)\n    } else {\n        return -1;   \u002F\u002F a should come before b\n    }\n};\n\nCollections.sort(arrList, comp);\n\u002F\u002F Result: [41, 33, 55, 22, 69, 90] (sorted by last digit: 1,3,5,2,9,0)\n```\n\n#### Comparator without Lambda (Traditional)\n```java\nComparator\u003CInteger> comp = new Comparator\u003CInteger>() {\n    @Override\n    public int compare(Integer a, Integer b) {\n        if (a % 10 > b % 10) {\n            return 1;\n        } else {\n            return -1;\n        }\n    }\n};\n\nCollections.sort(arrList, comp);\n```\n\n#### Set - Detecting Duplicates (O(n) vs O(n²))\n```java\n\u002F\u002F METHOD 1: Brute Force - O(n²) Time Complexity\npublic static boolean checkDuplicatesM1(int[] arr) {\n    for (int i = 0; i \u003C arr.length; i++) {\n        for (int j = i + 1; j \u003C arr.length; j++) {\n            if (arr[i] == arr[j]) {\n                return true;  \u002F\u002F Found duplicate\n            }\n        }\n    }\n    return false;\n}\n\n\u002F\u002F METHOD 2: Using HashSet - O(n) Time Complexity ⚡\npublic static boolean checkDuplicatesM2(int[] arr) {\n    Set\u003CInteger> hashSet = new HashSet\u003C>();\n    for (int num : arr) {\n        if (hashSet.contains(num)) {\n            return true;  \u002F\u002F Duplicate found\n        } else {\n            hashSet.add(num);\n        }\n    }\n    return false;\n}\n```\n\n#### Queue - Finding K Largest Elements\n```java\n\u002F\u002F Using MinHeap (PriorityQueue)\nQueue\u003CInteger> pq = new PriorityQueue\u003C>();\nint[] arr = {5, 1, 10, 3, 12, 2, 8};\nint k = 3;\n\nfor (int num : arr) {\n    pq.add(num);\n    if (k \u003C pq.size()) {\n        pq.poll();  \u002F\u002F Remove smallest to keep k largest\n    }\n}\n\nSystem.out.println(pq);  \u002F\u002F Output: [3, 5, 8] (or similar - heap order)\n```\n\n#### Iterator - Safe Traversal\n```java\nSet\u003CInteger> hashSet = new HashSet\u003C>();\nhashSet.add(4);\nhashSet.add(9);\nhashSet.add(300);\nhashSet.add(1);\n\nIterator\u003CInteger> it = hashSet.iterator();\n\nwhile (it.hasNext()) {\n    System.out.println(it.next());\n}\n```\n\n#### ArrayDeque - Deque Operations\n```java\nArrayDeque\u003CInteger> deque = new ArrayDeque\u003C>();\n\n\u002F\u002F Add at both ends\ndeque.offerFirst(0);   \u002F\u002F Add to front\ndeque.offer(91);       \u002F\u002F Add to back (default)\ndeque.offerLast(99);   \u002F\u002F Add to back\n\n\u002F\u002F Remove from both ends\nint front = deque.pollFirst();  \u002F\u002F Remove from front\nint back = deque.pollLast();    \u002F\u002F Remove from back\n\nSystem.out.println(deque);  \u002F\u002F Remaining elements\n```\n\n---\n\n### 🔢 Complexity Comparison\n\n| Operation | ArrayList | LinkedList | HashSet | TreeSet | PriorityQueue |\n|-----------|-----------|------------|---------|---------|---------------|\n| **Add** | O(1) amortized, O(n) at start | O(1) at ends, O(n) middle | O(1) avg | O(log n) | O(log n) |\n| **Remove** | O(n) | O(1) at ends, O(n) middle | O(1) avg | O(log n) | O(log n) |\n| **Search** | O(n) | O(n) | O(1) avg | O(log n) | O(n) |\n| **Space** | O(n) | O(n) | O(n) | O(n) | O(n) |\n| **Ordered** | ❌ Insertion | ❌ Insertion | ❌ No | ✅ Sorted | ✅ Heap |\n\n---\n\n### 🎨 Visual Examples\n\n**Collections Framework Relationship:**\n```\nIterable ← Top-level interface\n    │\n    └─► Collection ← All collections inherit\n        │\n        ├─► List (ArrayList, LinkedList, Stack)\n        │   └─ [1, 2, 2, 3] ← Duplicates allowed, indexed\n        │\n        ├─► Set (HashSet, TreeSet, LinkedHashSet)\n        │   └─ {1, 2, 3} ← No duplicates, no index\n        │\n        └─► Queue (PriorityQueue, ArrayDeque)\n            └─ [1 → 2 → 3] ← FIFO\u002FPriority order\n```\n\n**HashSet vs TreeSet vs LinkedHashSet:**\n```\nOriginal: 4, 9, 300, 1, 77\n\nHashSet:         {1, 4, 9, 77, 300}      (Random order)\nTreeSet:         {1, 4, 9, 77, 300}      (Sorted order) ⚡\nLinkedHashSet:   {4, 9, 300, 1, 77}      (Insertion order)\n```\n\n**PriorityQueue K-Largest Example:**\n```\nArray: [5, 1, 10, 3, 12, 2, 8], K = 3\n\nStep 1: Add all, remove smallest when size > k\nStep 2: Min-heap keeps: [3, 5, 8]\n        (These are the 3 largest elements)\n```\n\n---\n\n### 🧪 Practice Problems\n\n**🟢 Easy**\n1. Create a list, add elements, iterate using Iterator\n2. Create a HashSet, add numbers with duplicates - verify duplicates are ignored\n3. Sort a list using Collections.sort()\n4. Find the maximum element using TreeSet\n\n**🟡 Medium**\n5. Detect duplicates in an array (use HashSet)\n6. Find k largest elements from an array (use PriorityQueue)\n7. Create custom Comparator to sort by last digit of number\n8. Implement a queue using LinkedList\n\n**🔴 Hard**\n9. Find common elements between two lists (use Set intersection)\n10. Implement LRU Cache using LinkedHashMap + HashMap\n11. Sort objects using custom Comparator (compare multiple fields)\n12. Find all pairs in array that sum to target (use HashSet for O(n))\n\n---\n\n### ⚠️ Common Mistakes\n\n| ❌ Mistake | ✅ Solution | 💭 Why It Matters |\n|-----------|-----------|------------------|\n| Using ArrayList when frequent deletions needed | Use LinkedList for middle deletions | O(n) vs O(1) difference |\n| Forgetting that Set doesn't allow duplicates | Use List if duplicates needed | Sets silently ignore duplicate adds |\n| Creating HashSet with large objects | Override hashCode() and equals() | Default implementation may cause collisions |\n| Sorting with wrong Comparator logic | Remember: return -1 (before), 0 (equal), 1 (after) | Reverse logic = reverse sort |\n| Using Iterator.next() without hasNext() | Always check hasNext() first | Causes NoSuchElementException |\n| Not knowing when to use each Set type | HashSet (fast), TreeSet (sorted), LinkedHashSet (order) | Choose based on requirement |\n| Adding to PriorityQueue then sorting | PriorityQueue already maintains heap order | Sorting again is wasteful |\n\n---\n\n### 🔗 External Resources\n\n- 📺 **VisuAlgo - Hash Table & Heap**: [Visualize Set & Queue Operations](https:\u002F\u002Fvisualgo.net\u002F)\n- 📖 **Oracle Java Docs**: [Collections Framework](https:\u002F\u002Fdocs.oracle.com\u002Fjavase\u002Ftutorial\u002Fcollections\u002F)\n- 📖 **GeeksforGeeks**: [Java Collections Framework](https:\u002F\u002Fwww.geeksforgeeks.org\u002Fcollections-in-java-2\u002F)\n- 🎥 **YouTube**: \"Collections Framework Explained\" - Code with Harry\n- 📘 **LeetCode**: Filter problems by \"Design\", \"Hash Table\", \"Heap\" tags\n\n---\n\n### 📌 Key Takeaways\n\n💡 **Collections Framework = Iterable → Collection → List\u002FSet\u002FQueue** - Know the hierarchy!  \n💡 **Choose wisely**: ArrayList (fast access), LinkedList (fast ops), Set (unique), Queue (ordered processing)  \n💡 **HashSet is O(1)** - Use for duplicate detection and fast lookups  \n💡 **Comparators control sorting** - Lambda expressions make code clean  \n💡 **PriorityQueue is a min-heap** - Perfect for k-largest problems  \n💡 **Iterator is safer** than for-loop when removing elements  \n\n---\n\n## Day 4: Stacks\n\n**Status**: 🔴 **COMPLETED** | **Difficulty**: 🟡 **Medium** | **File**: `Day4Stacks.java`\n\n### 🎯 What You'll Learn\n- Complete **Comparators** concepts using Lambda expressions (sorting strategies)\n- Understand **Map Interface** deeply (HashMap, LinkedHashMap, TreeMap)\n- Implement **Stacks using Arrays, ArrayList, and Linked List**\n- Solve real stack problems: **Valid Parentheses** and **Next Greater Element**\n- Master **LIFO (Last-In-First-Out)** principle and its applications\n\n### 📚 Concepts Explained\n\n#### Comparators - Sorting Strategies\n\nA **Comparator** is a functional interface used to define custom sorting logic. It allows you to sort collections based on specific criteria using lambda expressions or anonymous classes.\n\n**Comparator Basics:**\n```\ncompare(a, b) returns:\n  > 0  : a comes after b\n  = 0  : a and b are equal\n  \u003C 0  : a comes before b\n```\n\n**Common Sorting Strategies:**\n\n1. **Sort by Last Digit (Units Place)**\n```\nArray: [99, 19, 23, 56, 76, 10, 31]\nBy last digit: [10, 31, 23, 56, 76, 99, 19] (0,1,3,6,6,9,9)\n```\n\n2. **Sort by Odd\u002FEven**\n```\nOdd numbers before even numbers (or vice versa)\n[1, 3, 5, 7] before [2, 4, 6, 8]\n```\n\n**Lambda Expression Syntax:**\n```\nComparator\u003CInteger> comp = (Integer a, Integer b) -> {\n    if (a % 10 > b % 10) return 1;   \u002F\u002F a after b\n    else return -1;                  \u002F\u002F a before b\n};\n```\n\n---\n\n#### Map Interface Hierarchy\n\nThe Map interface provides key-value pair storage. Let's explore three implementations:\n\n```\nMap Interface\n├─ HashMap: Fast lookup, random order, O(1) average\n├─ TreeMap: Sorted by keys, O(log n), navigable\n└─ LinkedHashMap: Maintains insertion order, O(1) average\n```\n\n**HashMap** - No Order Guarantee\n```\nHashMap:     {3→Sejal, 1→Mohini, 51→Mohini, 10→Mohini, 2→Shivam}\n             (Random order)\n```\n\n**TreeMap** - Sorted by Keys\n```\nTreeMap:     {1→Mohini, 2→Shivam, 3→Sejal, 10→Mohini, 51→Mohini}\n             (Sorted ascending)\n```\n\n**LinkedHashMap** - Insertion Order\n```\nLinkedHashMap: {3→Sejal, 1→Mohini, 51→Mohini, 10→Mohini, 2→Shivam}\n               (Same order as insertion)\n```\n\n---\n\n#### Stack Data Structure\n\nA **Stack** is a **LIFO (Last-In-First-Out)** data structure where:\n- Elements are added to the **top** (push)\n- Elements are removed from the **top** (pop)\n- The last element added is the first one removed\n\n```\nPush 3:    [3]\nPush 2:    [3, 2]\nPush 1:    [3, 2, 1]  ← Top\nPop:       [3, 2]     (Returns 1)\nPop:       [3]        (Returns 2)\n```\n\n**Stack Operations:**\n- **Push** - Add element to top: O(1)\n- **Pop** - Remove element from top: O(1)\n- **Peek** - View top element: O(1)\n- **isEmpty\u002FisFull** - Check status: O(1)\n\n---\n\n### 💻 Key Code Snippets\n\n#### Comparators - Sort by Last Digit (Lambda Expression)\n```java\n\u002F\u002F Sorting by last digit of numbers\nList\u003CInteger> arrList = new ArrayList\u003C>(Arrays.asList(99, 19, 23, 56, 76, 10, 31));\n\nComparator\u003CInteger> comp = (Integer a, Integer b) -> {\n    if (a % 10 > b % 10) {\n        return 1;    \u002F\u002F a should come after b (ascending by last digit)\n    } else {\n        return -1;   \u002F\u002F a should come before b\n    }\n};\n\nSystem.out.println(arrList);\nCollections.sort(arrList, comp);\nSystem.out.println(arrList);\n\u002F\u002F Result: [10, 31, 23, 56, 76, 99, 19] (sorted by last digit: 0,1,3,6,6,9,9)\n```\n\n#### Comparators - Sort by Odd\u002FEven\n```java\n\u002F\u002F Sort odd numbers before even numbers\nComparator\u003CInteger> comp2 = (Integer a, Integer b) -> {\n    if (a % 2 == 0) {\n        return 1;    \u002F\u002F Even numbers come after\n    } else {\n        return -1;   \u002F\u002F Odd numbers come before\n    }\n};\n\nSystem.out.println(arrList);\nCollections.sort(arrList, comp2);\nSystem.out.println(arrList);  \n\u002F\u002F Odd numbers appear first: [99, 19, 23, 31, 23, 56, 76, 10]\n```\n\n#### HashMap - Element Frequency (n\u002F3 times)\n```java\n\u002F\u002F Find all elements occurring more than n\u002F3 times\npublic static void elementMoreThanN3() {\n    Map\u003CInteger, Integer> hashMap = new HashMap\u003C>();\n    int[] arr = {1, 4, 1, 4, 2, 1, 7, 9, 1};  \u002F\u002F n = 9, n\u002F3 = 3\n    int n = arr.length;\n    \n    \u002F\u002F Count frequency of each element\n    for (int i = 0; i \u003C arr.length; i++) {\n        if (hashMap.containsKey(arr[i])) {\n            hashMap.put(arr[i], hashMap.get(arr[i]) + 1);\n        } else {\n            hashMap.put(arr[i], 1);\n        }\n    }\n    \n    \u002F\u002F Find elements with frequency >= n\u002F3\n    for (Map.Entry\u003CInteger, Integer> e : hashMap.entrySet()) {\n        if (e.getValue() >= (n \u002F 3)) {\n            System.out.print(e.getKey() + \" \");\n        }\n    }\n    \u002F\u002F Output: 1 4 (both occur 4 times, which is > 3)\n}\n```\n\n#### TreeMap - Built-in Methods\n```java\nMap\u003CString, String> treeMap = new TreeMap\u003C>();\ntreeMap.put(\"name\", \"Shivam\");\ntreeMap.put(\"isTrainer\", \"True\");\ntreeMap.put(\"topic\", \"Maps\");\n\n\u002F\u002F Check key existence\nSystem.out.println(treeMap.containsKey(\"names\"));  \u002F\u002F false\n\n\u002F\u002F Get value\nSystem.out.println(treeMap.get(\"name\"));  \u002F\u002F Shivam\n\n\u002F\u002F Put if key doesn't exist\ntreeMap.putIfAbsent(\"author\", \"anonymous\");\n\n\u002F\u002F Iterate through entries\nfor (Map.Entry\u003CString, String> data: treeMap.entrySet()) {\n    System.out.println(data.getKey() + \" -> \" + data.getValue());\n}\n\u002F\u002F Output (sorted by key):\n\u002F\u002F author -> anonymous\n\u002F\u002F isTrainer -> True\n\u002F\u002F name -> Shivam\n\u002F\u002F topic -> Maps\n```\n\n#### Stack Implementation Using Array\n```java\npublic class StackArray {\n    int[] arr;\n    int size;\n    int top = -1;\n    \n    public StackArray(int size) {\n        this.size = size;\n        arr = new int[size];\n    }\n    \n    public boolean isFull() {\n        return arr.length - 1 == top;\n    }\n    \n    public boolean isEmpty() {\n        return top == -1;\n    }\n    \n    public int peek() {\n        if (isEmpty()) {\n            System.out.println(\"Stack is Empty || UNDERFLOW\");\n            return -1;\n        }\n        return arr[top];\n    }\n    \n    public void push(int data) {\n        if (isFull()) {\n            System.out.println(\"Stack is Full || OVERFLOW\");\n        } else {\n            top++;\n            arr[top] = data;\n        }\n    }\n    \n    public int pop() {\n        if (isEmpty()) {\n            System.out.println(\"Stack is Empty || UNDERFLOW\");\n            return -1;\n        }\n        int lastEle = arr[top];\n        top--;\n        return lastEle;\n    }\n}\n```\n\n#### Stack Implementation Using ArrayList\n```java\npublic class StackArrayList {\n    List\u003CInteger> arrList = new ArrayList\u003C>();\n    int top = -1;\n    \n    public boolean isEmpty() {\n        return top == -1;\n    }\n    \n    public void push(int data) {\n        arrList.add(data);\n        top++;\n    }\n    \n    public int pop() {\n        if (isEmpty()) {\n            System.out.println(\"Stack is Empty !!!\");\n            return -1;\n        }\n        int lastEle = arrList.get(top);\n        arrList.remove(top);\n        top--;\n        return lastEle;\n    }\n    \n    public int peek() {\n        if (isEmpty()) {\n            System.out.println(\"Stack is Empty !!!\");\n            return -1;\n        }\n        return arrList.get(top);\n    }\n}\n```\n\n#### Valid Parentheses - Method 1 (Basic Approach)\n```java\n\u002F\u002F Check if string has valid parentheses\npublic class ValidParentheses1 {\n    public static void main(String[] args) {\n        Stack\u003CCharacter> stk = new Stack\u003C>();\n        boolean flag = true;\n        String s = \"(({}))\";  \n        \n        if (s.equals(\"\")) {\n            System.out.println(\"String is Empty !!!\");\n        } else {\n            for (int i = 0; i \u003C s.length(); i++) {\n                \u002F\u002F Push opening brackets\n                if (s.charAt(i) == '(' || s.charAt(i) == '{' || s.charAt(i) == '[') {\n                    stk.push(s.charAt(i));\n                } \n                \u002F\u002F Match closing brackets\n                else {\n                    if (!stk.isEmpty()) {\n                        if ((stk.peek() == '(' && s.charAt(i) == ')') ||\n                            (stk.peek() == '{' && s.charAt(i) == '}') ||\n                            (stk.peek() == '[' && s.charAt(i) == ']')) {\n                            stk.pop();\n                        }\n                    } else {\n                        flag = false;\n                        break;\n                    }\n                }\n            }\n            System.out.println(flag ? \"Valid Parentheses\" : \"Invalid Parentheses\");\n        }\n    }\n}\n```\n\n#### Valid Parentheses - Method 2 (Using HashMap)\n```java\n\u002F\u002F More elegant approach using Map for bracket matching\npublic class ValidParentheses2 {\n    public static boolean validParentheses(Stack\u003CCharacter> stk, String s) {\n        Map\u003CCharacter, Character> map = new HashMap\u003C>();\n        map.put(')', '(');\n        map.put('}', '{');\n        map.put(']', '[');\n        \n        if (s.equals(\"\"))\n            return false;\n        \n        for (int i = 0; i \u003C s.length(); i++) {\n            \u002F\u002F Push opening brackets\n            if (s.charAt(i) == '(' || s.charAt(i) == '[' || s.charAt(i) == '{') {\n                stk.push(s.charAt(i));\n            }\n            \u002F\u002F Match closing brackets using map\n            else {\n                if (stk.isEmpty())\n                    return false;\n                if (stk.peek().equals(map.get(s.charAt(i)))) {\n                    stk.pop();\n                }\n            }\n        }\n        return stk.isEmpty();  \u002F\u002F Stack should be empty for valid string\n    }\n    \n    public static void main(String[] args) {\n        Stack\u003CCharacter> stk = new Stack\u003C>();\n        String s = \"(({}))\";  \n        boolean res = validParentheses(stk, s);\n        System.out.println(res);  \u002F\u002F Output: true\n    }\n}\n```\n\n#### Next Greater Element\n```java\n\u002F\u002F Find the next greater element for each element in array\n\u002F\u002F Array: [4, 5, 2, 10, 8]\n\u002F\u002F Result: [5, 10, 10, -1, -1]  (Next greater to right, -1 if none)\n\npublic class NextGreaterElement {\n    public static int[] nextGreaterElement(Stack\u003CInteger> stk, int[] arr, int[] res) {\n        \u002F\u002F Traverse array from right to left\n        for (int i = arr.length - 1; i >= 0; i--) {\n            \u002F\u002F Pop elements smaller than current\n            while (!stk.isEmpty()) {\n                if (stk.peek() > arr[i]) {\n                    res[i] = stk.peek();  \u002F\u002F Found next greater\n                    break;\n                } else {\n                    stk.pop();  \u002F\u002F Remove smaller elements\n                }\n            }\n            stk.push(arr[i]);  \u002F\u002F Push current element\n        }\n        return res;\n    }\n\n    public static void main(String[] args) {\n        Stack\u003CInteger> stk = new Stack\u003C>();\n        int[] arr = {4, 5, 2, 10, 8};\n        int n = arr.length;\n        int[] res = new int[n];\n        Arrays.fill(res, -1);  \u002F\u002F Initialize with -1\n        \n        res = nextGreaterElement(stk, arr, res);\n        \n        for (int val : res) {\n            System.out.print(val + \" \");\n        }\n        \u002F\u002F Output: 5 10 10 -1 -1\n    }\n}\n```\n\n---\n\n### 🔢 Complexity Analysis\n\n| Operation | Array Stack | ArrayList Stack | LinkedList Stack | HashMap | TreeMap | LinkedHashMap |\n|-----------|-------------|-----------------|------------------|---------|---------|---------------|\n| **Push** | O(1) | O(1) amortized | O(1) | - | - | - |\n| **Pop** | O(1) | O(1) | O(1) | - | - | - |\n| **Peek** | O(1) | O(1) | O(1) | - | - | - |\n| **Insert (Map)** | - | - | - | O(1) avg | O(log n) | O(1) avg |\n| **Delete (Map)** | - | - | - | O(1) avg | O(log n) | O(1) avg |\n| **Search (Map)** | - | - | - | O(1) avg | O(log n) | O(1) avg |\n| **Space** | O(n) fixed | O(n) dynamic | O(n) dynamic | O(n) | O(n) | O(n) |\n\n---\n\n### 🎨 Visual Examples\n\n**Valid Parentheses Matching:**\n```\nString: \"(({}))\"\n        \nPush '('    → Stack: [(]\nPush '('    → Stack: [(, (]\nPush '{'    → Stack: [(, (, {]\nPush '}'    → Match! Pop '{' → Stack: [(, (]\nPush ')'    → Match! Pop '(' → Stack: [(\nPush ')'    → Match! Pop '(' → Stack: []\nResult: VALID! ✓\n\nInvalid: \"(())\" → Extra closing bracket → INVALID!\n```\n\n**Next Greater Element:**\n```\nArray:  [4, 5, 2, 10, 8]\n\nFor 8 (rightmost): No element > 8 to right → -1\nFor 10: No element > 10 to right → -1\nFor 2: 10 is greater and to right → 10\nFor 5: 10 is greater and to right → 10\nFor 4: 5 is greater and to right → 5\n\nResult: [5, 10, 10, -1, -1]\n```\n\n**Map Comparison:**\n```\nInsertion Order: {3→Sejal, 1→Mohini, 51→Mohini, 10→Mohini, 2→Shivam}\n\nHashMap:       {3→Sejal, 1→Mohini, 51→Mohini, 10→Mohini, 2→Shivam}  (Random)\nTreeMap:       {1→Mohini, 2→Shivam, 3→Sejal, 10→Mohini, 51→Mohini}  (Sorted keys)\nLinkedHashMap: {3→Sejal, 1→Mohini, 51→Mohini, 10→Mohini, 2→Shivam}  (Insertion)\n```\n\n---\n\n### 🧪 Practice Problems\n\n**🟢 Easy**\n1. Create a Comparator to sort numbers by their last digit\n2. Create a Comparator to sort odd\u002Feven numbers\n3. Count occurrences of elements using HashMap\n4. Check if a string contains only valid parentheses\n\n**🟡 Medium**\n5. Implement stack using array and test push\u002Fpop\u002Fpeek operations\n6. Implement stack using ArrayList\n7. Next Greater Element to the right in an array\n8. Find all elements occurring more than n\u002F3 times using HashMap\n9. TreeMap operations and sorting by keys\n10. Reverse a string using stack\n\n**🔴 Hard**\n11. Largest rectangle in histogram (uses stack)\n12. Trapping rainwater (two-pointer + stack hybrid)\n13. Daily temperatures (next greater variant)\n14. Implement Min Stack (push, pop, peek, getMin all O(1))\n\n---\n\n### ⚠️ Common Mistakes\n\n| ❌ Mistake | ✅ Solution | 💭 Why It Matters |\n|-----------|-----------|-------------------|\n| Confusing HashMap and TreeMap | Use HashMap for fast O(1) lookup, TreeMap when sorted order needed | Performance difference: O(1) vs O(log n) |\n| Forgetting to decrement `top` in array stack pop | Always do `top--` after popping | Otherwise top doesn't move, stack breaks |\n| Using wrong Map implementation | LinkedHashMap ≠ TreeMap (insertion vs sorted) | Different use cases! |\n| Not checking isEmpty() before pop\u002Fpeek | Always check first | Prevents null errors or wrong values |\n| Using stack when queue would be better | Think LIFO vs FIFO requirement | Wrong data structure = wrong output |\n| Parentheses matching logic reversed | Push opening, pop on closing, check match | Reversed logic gives opposite results |\n| Not initializing result array in NGE | Use Arrays.fill(res, -1) | Otherwise shows 0 instead of -1 |\n| Matching all bracket types at once | Use separate conditions for each type | Prevents cross-type matching errors |\n\n---\n\n### 🔗 External Resources\n\n- 📺 **VisuAlgo - Stack & Queue**: [Visualize Stack Operations](https:\u002F\u002Fvisualgo.net\u002Fen\u002Flist)\n- 📖 **GeeksforGeeks - Stack**: [Complete Stack Guide](https:\u002F\u002Fwww.geeksforgeeks.org\u002Fstack-data-structure\u002F)\n- 📖 **GeeksforGeeks - Map**: [HashMap vs TreeMap](https:\u002F\u002Fwww.geeksforgeeks.org\u002Fdifferences-between-hashmap-and-treemap-in-java\u002F)\n- 💡 **LeetCode Problems**: \n  - Valid Parentheses (#20)\n  - Next Greater Element (#496)\n  - Min Stack (#155)\n- 🎥 **YouTube**: \"Stack Problems Explained\" - Code Help\n\n---\n\n### 📌 Key Takeaways\n\n💡 **Comparators control custom sorting** - Lambda expressions make the code clean and concise  \n💡 **Choose your Map**: HashMap (fast O(1) lookup), TreeMap (sorted order O(log n)), LinkedHashMap (insertion order)  \n💡 **LIFO is the key** - Stack reverses order (last in = first out)  \n💡 **Valid Parentheses = Stack problem** - Push opening, pop on closing  \n💡 **NGE pattern** - Traverse right to left, use stack to track greater elements  \n💡 **Array vs ArrayList Stack** - Arrays are fixed size (overflow possible), ArrayList is dynamic  \n\n---\n\n\n---\n\n## Day 5: Stack Applications & Queues\n\n**Status**: 🔴 **COMPLETED** | **Difficulty**: 🔴 **Hard** | **File**: `Day5Queues.java`\n\n### 🎯 What You'll Learn\n- Solve monotonic stack problems: **Next\u002FPrevious Greater\u002FSmaller Element & Index**\n- Apply stack patterns to solve **Largest Rectangle in Histogram**\n- Implement **Queue using Arrays** (basic linear queue)\n- Implement **Circular Queue** using arrays with wrap-around logic\n\n---\n\n### 📚 Concepts Explained\n\n#### Monotonic Stack Patterns\n\nAll 6 variants follow the same template — the only differences are:\n1. **Direction** — traverse left-to-right (Previous) or right-to-left (Next)\n2. **Comparison** — `>` for Greater, `\u003C` for Smaller\n3. **What you push** — value (element problems) or index (index problems)\n\n```\nPattern Template:\n  for each element (from correct direction):\n      while stack not empty:\n          if stack.peek() satisfies condition → record result, break\n          else → pop\n      push current element (or index)\n```\n\n**6 Variants at a Glance:**\n\n| Problem | Direction | Condition | Push |\n|---------|-----------|-----------|------|\n| Next Greater Element | Right → Left | `peek > arr[i]` | value |\n| Next Smaller Element | Right → Left | `peek \u003C arr[i]` | value |\n| Previous Greater Element | Left → Right | `peek > arr[i]` | value |\n| Previous Smaller Element | Left → Right | `peek \u003C arr[i]` | value |\n| Previous Smaller Index | Left → Right | `arr[peek] \u003C arr[i]` | index |\n| Next Smaller Index | Right → Left | `arr[peek] \u003C arr[i]` | index |\n\n---\n\n#### Largest Rectangle in Histogram\n\nUses **Previous Smaller Index** (left boundary) + **Next Smaller Index** (right boundary) for each bar.\n\n```\nHistogram: [2, 1, 5, 6, 2, 3]\n\nFor each bar i:\n  width  = nextSmallerIndex[i] - previousSmallerIndex[i] - 1\n  area   = height[i] * width\n  answer = max of all areas\n\nAnswer: 10  (bars of height 5 and 6, width 2)\n```\n\n---\n\n#### Queue — Linear (Array-based)\n\n```\nFIFO: First In, First Out\n\nEnqueue 10 → [10]\nEnqueue 20 → [10, 20]\nEnqueue 30 → [10, 20, 30]\nDequeue    → [20, 30]   (10 removed from front)\n\nfront = 0, rear tracks last element\n```\n\n**Problem with linear queue:** after several dequeue+enqueue cycles, rear hits the end even if front has moved — wasted space. Solved by Circular Queue.\n\n---\n\n#### Circular Queue — Array-based\n\nRear wraps around to index 0 when it reaches the end:\n\n```\nSize = 3\n\nappend(10) → [10, _, _]   front=0, rear=0\nappend(20) → [10, 20, _]  front=0, rear=1\nappend(30) → [10, 20, 30] front=0, rear=2  (FULL)\ndequeue()  → [_, 20, 30]  front=1\nappend(50) → [50, 20, 30] rear wraps to 0!\n```\n\n**Key formulas:**\n```\nisFull  : (rear + 1) % size == front\nenqueue : rear = (rear + 1) % size   (or wrap manually)\ndequeue : front = (front + 1) % size\n```\n\n---\n\n### 💻 Key Code Snippets\n\n#### Next Greater Element\n```java\npublic static int[] nextGreaterElement(Stack\u003CInteger> stk, int[] arr, int[] res) {\n    stk.clear();\n    for (int i = arr.length - 1; i >= 0; i--) {\n        while (!stk.isEmpty()) {\n            if (stk.peek() > arr[i]) { res[i] = stk.peek(); break; }\n            else stk.pop();\n        }\n        stk.push(arr[i]);\n    }\n    return res;\n}\n\u002F\u002F arr = [4, 5, 2, 10, 8] → res = [5, 10, 10, -1, -1]\n```\n\n#### Previous Smaller Element\n```java\npublic static int[] previousSmallerElement(Stack\u003CInteger> stk, int[] arr, int[] res) {\n    stk.clear();\n    for (int i = 0; i \u003C arr.length; i++) {\n        while (!stk.isEmpty()) {\n            if (stk.peek() \u003C arr[i]) { res[i] = stk.peek(); break; }\n            else stk.pop();\n        }\n        stk.push(arr[i]);\n    }\n    return res;\n}\n```\n\n#### Previous Smaller Index & Next Smaller Index (used in Histogram)\n```java\npublic static int[] previousSmallerIndex(Stack\u003CInteger> stk, int[] arr, int[] res) {\n    stk.clear();\n    for (int i = 0; i \u003C arr.length; i++) {\n        while (!stk.isEmpty()) {\n            if (arr[stk.peek()] \u003C arr[i]) { res[i] = stk.peek(); break; }\n            else stk.pop();\n        }\n        stk.push(i);   \u002F\u002F Push INDEX not value\n    }\n    return res;\n}\n\npublic static int[] nextSmallerIndex(Stack\u003CInteger> stk, int[] arr, int[] res) {\n    stk.clear();\n    for (int i = arr.length - 1; i >= 0; i--) {\n        while (!stk.isEmpty()) {\n            if (arr[stk.peek()] \u003C arr[i]) { res[i] = stk.peek(); break; }\n            else stk.pop();\n        }\n        stk.push(i);   \u002F\u002F Push INDEX not value\n    }\n    return res;\n}\n```\n\n#### Largest Rectangle in Histogram\n```java\n\u002F\u002F arr = {2, 1, 5, 6, 2, 3}\nint[] leftRes = new int[n];   Arrays.fill(leftRes, -1);\nint[] rightRes = new int[n];  Arrays.fill(rightRes, n);\n\nleftRes  = previousSmallerIndex(stk, arr, leftRes);\nrightRes = nextSmallerIndex(stk, arr, rightRes);\n\nint maxArea = 0;\nfor (int i = 0; i \u003C arr.length; i++) {\n    int window = rightRes[i] - leftRes[i] - 1;\n    maxArea = Math.max(maxArea, arr[i] * window);\n}\n\u002F\u002F Output: 10\n```\n\n#### Circular Queue\n```java\npublic boolean isFull()  { return (rear + 1) % arr.length == front; }\npublic boolean isEmpty() { return front == -1 && rear == -1; }\n\npublic int append(int data) {\n    if (isFull())       { System.out.println(\"Queue is Full\"); return 0; }\n    else if (isEmpty()) { rear = 0; front = 0; }\n    else                { rear = (rear == arr.length - 1) ? 0 : rear + 1; }\n    arr[rear] = data;\n    return data;\n}\n\npublic int dequeue() {\n    if (isEmpty()) { System.out.println(\"Queue is Empty !!!\"); return -1; }\n    int removed = arr[front];\n    if (rear == front) { front = -1; rear = -1; }\n    else               { front = (front + 1) % arr.length; }\n    return removed;\n}\n```\n\n---\n\n### 🔢 Complexity Analysis\n\n| Problem | Time | Space | Notes |\n|---------|------|-------|-------|\n| Next\u002FPrev Greater\u002FSmaller Element | O(n) | O(n) | Each element pushed\u002Fpopped once |\n| Next\u002FPrev Smaller Index | O(n) | O(n) | Same pattern, push index |\n| Largest Rectangle in Histogram | O(n) | O(n) | Two index passes + one area pass |\n| Queue (Array) Enqueue | O(1) | O(1) | Direct rear insert |\n| Queue (Array) Dequeue | O(n) | O(1) | Shifts all elements left ⚠️ |\n| Circular Queue Enqueue | O(1) | O(1) | Wrap with modulo |\n| Circular Queue Dequeue | O(1) | O(1) | No shifting needed ⚡ |\n\n---\n\n### 🎨 Visual Examples\n\n**Monotonic Stack — Next Greater Element:**\n```\narr = [4, 5, 2, 10, 8],  traverse right → left\n\ni=4: stk=[]       → res[4]=-1, push 8    stk=[8]\ni=3: 8 \u003C 10, pop  → stk=[], res[3]=-1,   push 10  stk=[10]\ni=2: 10 > 2       → res[2]=10, push 2    stk=[10,2]\ni=1: 2 \u003C 5, pop; 10 > 5 → res[1]=10, push 5  stk=[10,5]\ni=0: 5 > 4        → res[0]=5,  push 4    stk=[10,5,4]\n\nResult: [5, 10, 10, -1, -1]\n```\n\n**Circular Queue Wrap-around:**\n```\nsize=3: append(10)→append(20)→append(30)→dequeue()→append(50)\n\nIndex:   0    1    2\n         [50, 20, 30]\n              ▲    ▲\n            front  rear=0 (wrapped!)\n```\n\n---\n\n### 🧪 Practice Problems\n\n**🟢 Easy**\n1. Find Next Greater Element for every array element\n2. Find Previous Smaller Element for every array element\n3. Implement a basic Queue using array\n\n**🟡 Medium**\n4. Find Next Greater Element index (not value)\n5. Implement Circular Queue with all edge cases\n6. Daily Temperatures (LeetCode #739) — Next Greater variant\n\n**🔴 Hard**\n7. Largest Rectangle in Histogram (LeetCode #84)\n8. Maximal Rectangle (LeetCode #85) — uses histogram approach per row\n9. Sum of Subarray Minimums (LeetCode #907) — uses previous\u002Fnext smaller\n\n---\n\n### ⚠️ Common Mistakes\n\n| ❌ Mistake | ✅ Solution |\n|-----------|-----------|\n| Using value instead of index in histogram | Push `i` not `arr[i]` for index variants |\n| Wrong default fill for index arrays | `fill(left, -1)` and `fill(right, n)` — boundaries matter |\n| Linear queue \"false full\" | Use circular queue; rear wrapping fixes wasted space |\n| Forgetting to reset `front=rear=-1` when last element dequeued | Check `front == rear` before advancing pointers |\n| `isFull` check wrong in circular queue | Must be `(rear + 1) % size == front`, not `rear == size-1` |\n\n---\n\n### 📌 Key Takeaways\n\n💡 **All 6 stack variants share one template** — change direction + comparison operator  \n💡 **Histogram = Previous Smaller Index + Next Smaller Index** — two passes, one answer  \n💡 **Circular Queue fixes wasted space** in linear queues using modulo wrap-around  \n💡 **O(n) for monotonic stack** — each element is pushed and popped at most once  \n💡 **Index variants** store indices on stack; compare `arr[stk.peek()]` not `stk.peek()`\n\n---\n\n\n---\n\n## Day 6: Two Pointers\n\n**Status**: 🔴 **COMPLETED** | **Difficulty**: 🟡 **Medium** | **File**: `Day6TwoPointers.java`\n\n### 🎯 What You'll Learn\n- Master the **Two Pointer Technique** across 4 different patterns\n- Solve **String Problems**: Palindrome checking, character matching\n- Implement **Array Merging**: Merge two sorted arrays efficiently\n- Apply **Sliding Window**: Find longest substring without repeats\n- Solve **Optimization Problems**: Container with Most Water\n\n### 📚 Concepts Explained\n\n#### What is the Two Pointer Technique?\n\nThe **Two Pointer Technique** uses two pointers (indices) that move through a data structure (usually an array or string) to solve problems efficiently. Instead of nested loops (O(n²)), we traverse smartly with two pointers, achieving O(n) in many cases.\n\n**Core Idea:**\nInstead of:   Nested loops → O(n²) ❌\nUse:          Two pointers → O(n) ✅\n\n#### 4 Types of Two Pointer Patterns\n\n**Type 1: Opposite Direction Pointers** (Start and End)\nLeft pointer at start → Right pointer at end\nThey move TOWARDS each other until they meet\nUse cases: Palindrome, reversal, container problems\n\n**Type 2: Same Direction Pointers** (Slow and Fast)\nBoth start at beginning\nFast pointer moves ahead → Slow pointer follows\nThey maintain a window\u002Fgap\nUse cases: Remove duplicates, linked list cycle detection\n\n**Type 3: Sliding Window** (Variable Window)\nLeft and right pointers define a window\nWindow size changes based on conditions\nTrack max\u002Fmin within the window\nUse cases: Longest substring, max sum subarray\n\n**Type 4: Fixed Window** (Constant Size)\nTwo pointers maintain fixed distance\nSlide together across array\nCalculate sum\u002Favg for each window\nUse cases: Maximum average subarray, k-size window\n\n---\n\n### 💻 Key Code Snippets\n\n#### Type 1: Palindrome Check (Opposite Direction)\n```java\npublic static void palindrome() {\n    \u002F\u002F Time: O(n) | Space: O(1)\n    \n    String original = \"racecar\";\n    int left = 0;\n    int right = original.length() - 1;\n    boolean flag = true;\n    \n    while (left \u003C= right) {\n        if (original.charAt(left) != original.charAt(right)) {\n            flag = false;\n            break;\n        }\n        left++;      \u002F\u002F Move left pointer forward\n        right--;     \u002F\u002F Move right pointer backward\n    }\n    \n    System.out.println(flag ? \"Palindrome\" : \"Not Palindrome\");\n    \u002F\u002F Output: Palindrome ✓\n}\n```\n\n**Why it works:**\n\"racecar\"\n^    ^\nl    r   → Compare 'r' == 'r' ✓\n^  ^\nl  r    → Compare 'a' == 'a' ✓\n^^\nlr     → Compare 'c' == 'c' ✓\nPointers meet → All matched → Palindrome!\n\n---\n\n#### Type 2: Remove Duplicates (Same Direction - Slow & Fast)\n```java\npublic static void removeDuplicates() {\n    \u002F\u002F Time: O(n) | Space: O(1)\n    \n    int[] arr = {2, 5, 2, 4, 4, 2, 5};\n    Arrays.sort(arr);  \u002F\u002F [2, 2, 2, 4, 4, 5, 5]\n    \n    int i = 0;  \u002F\u002F Slow pointer - position to place unique element\n    \n    while (i \u003C arr.length) {\n        arr[i] added to result\n        \n        int j = i + 1;  \u002F\u002F Fast pointer - find next different element\n        while (j \u003C arr.length && arr[j] == arr[i]) {\n            j++;  \u002F\u002F Skip duplicates\n        }\n        \n        i = j;  \u002F\u002F Move slow pointer to next different element\n    }\n    \n    \u002F\u002F Result: [2, 4, 5] - unique elements only\n}\n```\n\n**Pointer Movement Visualization:**\nArray:  [2, 2, 2, 4, 4, 5, 5]\ni           (add 2)\nj j j   (skip 2s, jump to 4)\n     i       (add 4)\n         j j (skip 4s)\n    \n     i       (add 5)\n             (no more duplicates)\n\n---\n\n#### Type 3: Sliding Window - Longest Substring Without Repeats\n```java\npublic static void longestSubstring() {\n    \u002F\u002F Time: O(n) | Space: O(1) - at most 26 characters\n    \n    Set\u003CCharacter> set = new HashSet\u003C>();\n    String s = \"abcabbcab\";\n    \n    int left = 0;\n    int maxLength = 0;\n    \n    for (int right = 0; right \u003C s.length(); right++) {\n        \u002F\u002F If character already exists, shrink window from left\n        while (set.contains(s.charAt(right))) {\n            set.remove(s.charAt(left));\n            left++;\n        }\n        \n        \u002F\u002F Add current character\n        set.add(s.charAt(right));\n        \n        \u002F\u002F Update max length\n        int window = right - left + 1;\n        maxLength = Math.max(window, maxLength);\n    }\n    \n    System.out.println(maxLength);  \u002F\u002F Output: 3 (\"abc\" or \"cab\")\n}\n```\n\n**Window Expansion & Contraction:**\nString: \"abcabbcab\"\nWindow progression:\n\"a\"      → length 1\n\"ab\"     → length 2\n\"abc\"    → length 3 (maxLength = 3)\n\"cab\"    → shrink: \"ab\" → \"cab\" → length 3\n...\nAnswer: 3\n\n---\n\n#### Type 3: Max Average Subarray (Fixed Window)\n```java\npublic static void maxAvgSubarray() {\n    \u002F\u002F Time: O(n) | Space: O(1)\n    \n    int[] arr = {1, 12, -5, -6, 50, 3};\n    int k = 4;  \u002F\u002F Window size\n    \n    int i = 0;\n    int j = 0;\n    int currentSum = 0;\n    int maxSum = 0;\n    \n    \u002F\u002F Build initial window\n    while (j \u003C k) {\n        currentSum += arr[j];\n        j++;\n    }\n    maxSum = currentSum;\n    \n    \u002F\u002F Slide the window: add new element, remove old element\n    while (j \u003C arr.length) {\n        currentSum += arr[j];        \u002F\u002F Add new right element\n        currentSum -= arr[i];        \u002F\u002F Remove old left element\n        maxSum = Math.max(currentSum, maxSum);\n        i++;\n        j++;\n    }\n    \n    System.out.println(maxSum \u002F k);  \u002F\u002F Average\n}\n```\n\n**Window Sliding Technique:**\nArray: [1, 12, -5, -6, 50, 3], K = 4\nWindow 1: [1, 12, -5, -6]  → Sum = 2\nWindow 2: [12, -5, -6, 50] → Sum = 51  ✓ Max\nWindow 3: [-5, -6, 50, 3]  → Sum = 42\nAnswer: maxSum = 51, average = 51\u002F4 = 12\n\n---\n\n#### Type 4: Merge Two Sorted Arrays (Opposite Direction - Merge Pattern)\n```java\npublic static void mergeSortedArrays() {\n    \u002F\u002F Time: O(n + m) | Space: O(n + m)\n    \n    int[] arr1 = {2, 5, 9, 12};\n    int[] arr2 = {4, 8, 16};\n    int[] res = new int[arr1.length + arr2.length];\n    \n    int i = 0;      \u002F\u002F Pointer for arr1\n    int j = 0;      \u002F\u002F Pointer for arr2\n    int resIndex = 0;  \u002F\u002F Pointer for result array\n    \n    \u002F\u002F Merge while both arrays have elements\n    while (i \u003C arr1.length && j \u003C arr2.length) {\n        if (arr1[i] \u003C arr2[j]) {\n            res[resIndex++] = arr1[i++];\n        } else {\n            res[resIndex++] = arr2[j++];\n        }\n    }\n    \n    \u002F\u002F Add remaining elements from arr1\n    while (i \u003C arr1.length) {\n        res[resIndex++] = arr1[i++];\n    }\n    \n    \u002F\u002F Add remaining elements from arr2\n    while (j \u003C arr2.length) {\n        res[resIndex++] = arr2[j++];\n    }\n    \n    \u002F\u002F Result: [2, 4, 5, 8, 9, 12, 16]\n}\n```\n\n**Merging Process:**\narr1 = [2, 5, 9, 12]\narr2 = [4, 8, 16]\nCompare 2 vs 4 → 2 is smaller → Add 2\nCompare 5 vs 4 → 4 is smaller → Add 4\nCompare 5 vs 8 → 5 is smaller → Add 5\nCompare 9 vs 8 → 8 is smaller → Add 8\nCompare 9 vs 16 → 9 is smaller → Add 9\nCompare 12 vs 16 → 12 is smaller → Add 12\narr2 still has 16 → Add 16\nResult: [2, 4, 5, 8, 9, 12, 16] ✓\n\n---\n\n#### Type 4: Container with Most Water (Optimization)\n```java\npublic static void containerWithMostWater() {\n    \u002F\u002F Time: O(n) | Space: O(1)\n    \n    int[] height = {1, 8, 6, 2, 5, 4, 8, 3, 7};\n    \n    int left = 0;\n    int right = height.length - 1;\n    int maxWater = 0;\n    \n    while (left \u003C right) {\n        \u002F\u002F Width = distance between pointers\n        int width = right - left;\n        \n        \u002F\u002F Height = minimum of two heights\n        int h = Math.min(height[left], height[right]);\n        \n        \u002F\u002F Area = width × height\n        int currentWater = h * width;\n        maxWater = Math.max(maxWater, currentWater);\n        \n        \u002F\u002F Move the pointer with smaller height\n        \u002F\u002F Why? To find potentially taller bar\n        if (height[left] \u003C height[right]) {\n            left++;\n        } else {\n            right--;\n        }\n    }\n    \n    System.out.println(maxWater);  \u002F\u002F Output: 49\n}\n```\n\n**Why Move Smaller Pointer?**\nheight = [1, 8, 6, 2, 5, 4, 8, 3, 7]\n^                          ^\nleft                       right\narea = min(1, 7) × 8 = 1 × 8 = 8\nMoving right won't help (width decreases, height capped at 1)\nSo move left to find taller bar:\n^                       ^\nleft                  right\narea = min(8, 7) × 7 = 7 × 7 = 49 ✓ Much better!\n\n---\n\n### 🔢 Complexity Comparison\n\n| Problem | Type | Time | Space | Notes |\n|---------|------|------|-------|-------|\n| **Palindrome** | Opposite | O(n) | O(1) | Compare from ends |\n| **Remove Duplicates** | Slow\u002FFast | O(n) | O(1) | In-place removal |\n| **Longest Substring** | Sliding Window | O(n) | O(1)* | Window expands\u002Fshrinks |\n| **Max Avg Subarray** | Fixed Window | O(n) | O(1) | Constant k-size window |\n| **Merge Arrays** | Merge Pattern | O(n+m) | O(n+m) | Requires result array |\n| **Container Water** | Greedy+Two Ptr | O(n) | O(1) | Move smaller height |\n\n*O(m) where m = character set size (26 for English)\n\n---\n\n### 🎨 Visual Examples\n\n**Palindrome Check Animation:**\n\"racecar\"\n↙   ↖\nl   r   Match? YES\n↙ ↖\nl r    Match? YES\n↙↖\nlr    Match? YES\nPointers crossed → PALINDROME! ✓\n\n**Sliding Window Growth & Shrink:**\nString: \"abcabbcab\"\n[a]         → length 1\n[ab]        → length 2\n[abc]       → length 3 ✓ MAX\n[ab]c       → 'c' duplicate, shrink\n[abc]ab     → length 3\n[cab]       → length 3\n[ab]ca      → 'a' duplicate, shrink\n...\nFinal Answer: 3\n\n**Container with Most Water Optimization:**\nHeights: [1, 8, 6, 2, 5, 4, 8, 3, 7]\n[0,    1,       2,       3,    8]\nleft=0, right=8\narea = min(1,7) × 8 = 8\nleft=1, right=8\narea = min(8,7) × 7 = 49 ← BEST!\nleft=2, right=8\narea = min(6,7) × 6 = 36\nContinue until pointers meet...\nAnswer: 49\n\n---\n\n### 🧪 Practice Problems\n\n**🟢 Easy**\n1. Check if string is palindrome\n2. Reverse a string using two pointers\n3. Merge two sorted arrays\n4. Check if array is sorted\n\n**🟡 Medium**\n5. Longest substring without repeating characters\n6. Maximum average subarray of size k\n7. Container with most water\n8. Remove duplicates from sorted array\n9. Two sum (sorted array) - find two numbers that sum to target\n10. Valid palindrome (ignore non-alphanumeric characters)\n\n**🔴 Hard**\n11. Trapping rain water (LeetCode #42)\n12. Minimum window substring\n13. Longest substring with k distinct characters\n14. Three sum (find three numbers that sum to 0) - uses two pointers with loop\n\n---\n\n### ⚠️ Common Mistakes\n\n| ❌ Mistake | ✅ Solution | 💭 Why It Matters |\n|-----------|-----------|-------------------|\n| Forgetting to move pointers | Always increment\u002Fdecrement in loop | Infinite loop otherwise! |\n| Wrong pointer movement direction | For palindrome: left++, right-- | Opposite directions needed |\n| Comparing wrong characters in palindrome | Use `charAt(left)` not `arr[left]` | Strings need charAt() |\n| Not handling overlapping window correctly | Use `while (set.contains())` before adding | Prevents duplicates in set |\n| Moving wrong pointer in container problem | Move pointer with SMALLER height | Moving taller won't increase area |\n| Forgetting remaining elements after merge | Always add leftover from both arrays | Incomplete merge otherwise |\n| Using >= instead of > in comparisons | Be precise with boundary conditions | Off-by-one errors happen |\n| Not tracking the correct window size | For fixed window: use `j - i + 1` | Incorrect area calculation |\n\n---\n\n### 🔗 External Resources\n\n- 📺 **VisuAlgo - Sorting**: [Visualize Two Pointer Merge](https:\u002F\u002Fvisualgo.net\u002Fen\u002Fsorting)\n- 📖 **GeeksforGeeks**: [Two Pointer Technique](https:\u002F\u002Fwww.geeksforgeeks.org\u002Ftwo-pointers-technique\u002F)\n- 📖 **LeetCode Problems**:\n  - Valid Palindrome (#125)\n  - Container with Most Water (#11)\n  - Longest Substring Without Repeating (#3)\n  - Merge Sorted Array (#88)\n- 🎥 **YouTube**: \"Two Pointer Technique Explained\" - Code with Harry\n\n---\n\n### 📌 Key Takeaways\n\n💡 **Two Pointers = O(n) instead of O(n²)** for many problems  \n💡 **Opposite direction** for palindrome, merging, water trapping  \n💡 **Same direction (slow\u002Ffast)** for duplicates, cycle detection  \n💡 **Sliding window** expands\u002Fshrinks based on condition  \n💡 **Fixed window** has constant size, slides linearly  \n💡 **Greedy choice** in container problem: move smaller height pointer  \n💡 **Always check boundaries** with \u003C= or \u003C to avoid off-by-one errors  \n\n---\n\n\u003C!-- End of Day 6: Two Pointers -->\n\n# 🔧 Reference Materials\n\n## Big O Complexity Cheat Sheet\n\n```\nBEST CASE      AVERAGE CASE     WORST CASE      NAME\n──────────────────────────────────────────────────────\nO(1)           O(1)             O(1)            Constant\nO(log n)       O(log n)         O(log n)        Logarithmic\nO(n)           O(n)             O(n)            Linear\nO(n log n)     O(n log n)       O(n log n)      Linearithmic\nO(n²)          O(n²)            O(n²)           Quadratic\nO(n³)          O(n³)            O(n³)           Cubic\nO(2ⁿ)          O(2ⁿ)            O(2ⁿ)           Exponential\nO(n!)          O(n!)            O(n!)           Factorial\n\nVisual Comparison (which is faster?):\n        O(1) ⚡⚡⚡\n        O(log n) ⚡⚡\n        O(n) ⚡\n        O(n log n) ⚡\n        O(n²) 🐢\n        O(2ⁿ) 🐌🐌🐌 (AVOID!)\n```\n\n---\n\n\n\n## Data Structure Complexity Quick Reference\n\n| Structure | Insert | Delete | Search | Space | Best For |\n|-----------|--------|--------|--------|-------|----------|\n| Array | O(n) | O(n) | O(n) | O(n) | Indexed access, cache-friendly |\n| Linked List | O(1)* | O(1)* | O(n) | O(n) | Dynamic size, frequent inserts |\n| Stack | O(1) | O(1) | O(n) | O(n) | LIFO, undo\u002Fredo, function calls |\n| Queue | O(1) | O(1) | O(n) | O(n) | FIFO, BFS, scheduling |\n| BST | O(log n) | O(log n) | O(log n) | O(n) | Sorted data, fast lookup |\n| Hash Table | O(1)** | O(1)** | O(1)** | O(n) | Fast lookups, no order needed |\n| Heap | O(log n) | O(log n) | O(n) | O(n) | Priority, min\u002Fmax |\n| Graph | - | - | O(V+E) | O(V+E) | Networks, relationships |\n\n*With reference to node  \n**Average case; O(n) worst case if hash collisions  \n\n---\n\n## 💡 Key Interview Questions by Topic\n\n### Linked Lists\n1. **Reverse a linked list** - Classic! 🎯\n2. **Detect cycle** - Floyd's algorithm (tortoise & hare)\n3. **Merge two sorted lists** - Practice merging technique\n4. **Find middle element** - Two pointer technique\n5. **Remove Nth node from end** - Edge cases matter\n\n### Stacks & Queues\n1. **Valid parentheses** - Stack use case\n2. **Min stack** - Track minimum while pushing\n3. **Implement queue using stacks** - Learn trade-offs\n4. **LRU Cache** - Combine hash map + doubly linked list\n\n### Trees\n1. **Inorder traversal** - Sorted output!\n2. **Lowest Common Ancestor** - Recursive thinking\n3. **Balanced tree check** - Recursion + height tracking\n4. **Level-order traversal** - BFS practice\n5. **Serialize\u002Fdeserialize** - Tricky but important\n\n### Graphs\n1. **Number of islands** - DFS\u002FBFS application\n2. **Topological sort** - DAG processing\n3. **Shortest path (Dijkstra)** - Priority queue needed\n4. **Detect cycle** - DFS with color marking\n5. **Connected components** - Union-Find data structure\n\n### Dynamic Programming\n1. **Climbing stairs** - Easy DP intro\n2. **0\u002F1 Knapsack** - Classic DP problem\n3. **Longest increasing subsequence** - Pattern recognition\n4. **Coin change** - Min coins for amount\n5. **Edit distance** - String transformation\n\n---\n\n## 🛠️ Useful Tools & Visualizers\n\n### Visualization Tools (Highly Recommended!)\n- 🌐 **[VisuAlgo](https:\u002F\u002Fvisualgo.net\u002F)** - Most comprehensive DSA visualizer\n- 🌐 **[Thinkful](https:\u002F\u002Fwww.thinkful.com\u002Flearn\u002Fdata-structures-part-one\u002F)** - Excellent tutorials\n- 🌐 **[PythonTutor](https:\u002F\u002Fpythontutor.com\u002F)** - Step-through execution (works for Java too!)\n- 🌐 **[LeetCode](https:\u002F\u002Fleetcode.com\u002F)** - 2000+ practice problems, discuss solutions\n- 🌐 **[HackerEarth](https:\u002F\u002Fwww.hackerearth.com\u002Fpractice\u002Fdata-structures\u002F)** - Competitive programming focus\n\n### Online Judges (Code & Test)\n- **LeetCode** - Best for interviews\n- **HackerRank** - Good tutorials + problems\n- **CodeChef** - Competitive programming\n- **AtCoder** - Educational content\n\n### YouTube Channels (Free Learning!)\n- 📺 **Abdul Bari** - Detailed DSA explanations\n- 📺 **Code with Harry** - Hindi\u002FEnglish, beginner-friendly\n- 📺 **Kunal Kushwaha** - Comprehensive DSA series\n- 📺 **Striver** - Interview-focused content\n\n---\n\n## ⚡ Pro Tips & Best Practices\n\n### 🎯 Before Writing Code\n1. **Understand the problem** - Restate it in your own words\n2. **Identify data structure** - Will you need array, tree, graph?\n3. **Plan the algorithm** - Pseudocode first!\n4. **Calculate complexity** - Will it be fast enough?\n\n### 🏗️ While Writing Code\n1. **Handle edge cases** - Empty, single element, maximum size\n2. **Use meaningful names** - `head` > `h`, `append` > `add`\n3. **Comment complex logic** - Future you will thank present you\n4. **Test as you go** - Don't wait until the end\n\n### ✅ Code Review Checklist\n- [ ] Does it compile without errors?\n- [ ] Does it handle null\u002Fempty cases?\n- [ ] Is time complexity acceptable?\n- [ ] Is space complexity optimized?\n- [ ] Is the code readable (another dev can understand)?\n- [ ] Are there any off-by-one errors?\n- [ ] Did I test with multiple inputs?\n\n### 🧠 Common Java Gotchas\n```java\n\u002F\u002F ❌ Bad: Modifying object passed as parameter\npublic void modify(Node node) {\n    node = null;  \u002F\u002F Doesn't affect original!\n}\n\n\u002F\u002F ✅ Good: Modify node's properties\npublic void modify(Node node) {\n    node.data = 0;  \u002F\u002F Changes the object\n}\n\n\u002F\u002F ❌ Bad: NullPointerException risk\nif (head.next != null) { }  \u002F\u002F What if head is null?\n\n\u002F\u002F ✅ Good: Check for null first\nif (head != null && head.next != null) { }\n\n\u002F\u002F ❌ Bad: Infinite loop\nwhile (current != null) {\n    current = current;  \u002F\u002F Never advances!\n}\n\n\u002F\u002F ✅",2,"2026-06-11 04:10:51","CREATED_QUERY"]