
Sky always blue
Control flow for algorithm
| Use case | Use this |
| Exit only the loop? Bonus → only the most inner loop | break |
| Skip this iteration and continue loop? | continue |
| Exit function early? | return |
Use-case of break
include(substring) {
const str = this.value;
const n = str.length;
const m = substring.length;
if(m === 0) return true;
if(m > n) return false;
for(let i=0; i <= n - m ; i++) {
let matches = true;
for(let j=0;j < m;j++) {
if(str[i+j]!== substring[j]) {
matches = false;
break;
}
}
if(matches) return true;
}
return false;
}
//stream API in java
*[Symbol.iterator]() {
for(let val of this.source) {
let include = true;
let result = val;
for(let operation of this.operations) {
if(operation.type === 'map') {
result = operation.cb(val);
}
if(operation.type === 'filter' && !operation.cb(val)) {
include = false; //stop applying further operations to this value (because one filter already rejected it).
}
}
if (include) yield result;
}
}
For of vs let i
🔁 for...of — When you care about values
✅ Use this when:
You only need the item itself (not the index).
You're looping through strings or arrays.
You don’t need to modify the original array (for strings, you can’t anyway—they're immutable).
📌 Example:
class Trie {
insert(text) {
let node = this.root;
for(let char of text) {
if(!node.children[char]) {
node.children[char] = new TrieNode();
}
node = node.children[char];
}
node.isEndOfWord = true;
}
}
🔁 for (let i = 0; i < ...) — When you need indexes
jsCopyEditfor (let i = 0; i < arr.length; i++) {
// use i and/or arr[i]
}
✅ Use this when:
You need the index (to track positions, or access neighbors).
You plan to modify the array.
You want to loop over part of the array or string (e.g., starting in the middle).
You might need to look ahead or behind in the sequence.
📌 Example:
jsCopyEditlet arr = ['a', 'b', 'c'];
for (let i = 0; i < arr.length; i++) {
if (i % 2 === 0) {
console.log(arr[i]); // a, c
}
}
| Use Case | Use for...of | Use for (let i = 0; ...) |
| Need just the value | ✅ | ✅ but overkill |
| Need the index | ❌ | ✅ |
| Need to modify elements | ❌ (can’t with strings) | ✅ |
| Need to skip or jump steps | ❌ | ✅ |
| Looping over object properties | ❌ (use for...in or Object.keys) | ✅ |
Running time

Sort (array data structure)
Base-case for these smart sort-algorithm ?
Devide and conquer technical
Binary search arr ( when left >= right => can’t find the value)
QuickSort ( when left >= right => can’t partition anymore)
MergeSort ( when arr.length === 0 => can’t devide the value anymore)
Binary search array

Mergesort

Quicksort

Recursive


Recap
• Recursion is when a function calls itself.
• Every recursive function has two cases: the base case
and the recursive case.
• A stack has two operations: push and pop.
• All function calls go onto the call stack.
• The call stack can get very large, which takes up a lot of memory.
🌳 Why Recursion Fits Trees Perfectly
1. Trees Are Naturally Recursive Structures
A tree is defined in terms of smaller trees:
textCopyEditTree:
- A node (with data)
- Zero or more child trees
So a tree is self-similar — the same structure repeats within itself, just smaller. This is exactly what recursion is great at!
2. Recursion Mirrors Tree Traversal
To traverse a tree, you typically:
Do something at the current node
Then recursively do the same thing to each child node
Example in JavaScript (pre-order traversal):
jsCopyEditfunction traverse(node) {
console.log(node.value); // Visit current node
for (let child of node.children) {
traverse(child); // Visit child recursively
}
}
This "call itself on smaller parts" is exactly how recursion works.
3. Call Stack = Implicit Tree Path
When recursion goes deep:
Each function call remembers "where it came from"
That’s like walking down a branch in the tree
When you return (go back up), you unwind the tree path
The function stack follows the shape of the tree path!
4. Cleaner and Simpler Code
Without recursion, tree algorithms are harder to write. Compare:
With recursion:
jsCopyEditfunction sumTree(node) {
if (!node) return 0;
return node.value + sumTree(node.left) + sumTree(node.right);
}
Without recursion (iterative with stack):
jsCopyEditfunction sumTreeIterative(root) {
if (!root) return 0;
let stack = [root], sum = 0;
while (stack.length) {
let node = stack.pop();
sum += node.value;
if (node.right) stack.push(node.right);
if (node.left) stack.push(node.left);
}
return sum;
}
Recursion looks more like the structure of the problem.
🧠 Summary
| Tree Property | Why Recursion Fits |
| Self-similar structure | Recursion breaks problems into parts |
| Branching paths | Recursive calls explore each branch |
| Going deep & back up | Call stack mirrors tree path |
| Natural expression of traversal | Cleaner and intuitive code |
If you’re building a decision system, DOM traversal, file structure, AI reasoning, or game trees, recursion is often the most natural fit.
Main Signals for Using Two-Pointer Technique
🔁 1. Comparing or checking elements from both ends
You need to compare, reverse, or meet in the middle
Keywords: "is it a palindrome?", "reverse", "mirror", "container", "sorted"
Examples:
isPalindrome("abba")
reverseString(["h", "e", "l", "l", "o"])
containerWithMostWater(height)
➕ 2. Finding a pair/triplet that satisfies a condition
Usually used in sorted arrays
Goal: find two numbers that sum to a target, or find duplicates
Examples:
twoSumSorted([2,7,11,15], target = 9)
3Sum,removeDuplicatesSorted
📏 3. Shrinking or sliding a window
You're finding substrings, subarrays, or ranges
Need to dynamically expand and contract a window of elements
Examples:
longestSubstringWithoutRepeatingCharacters("abcabcbb")
minWindowSubstring(s, t)
maximumSumSubarray
✂️ 4. In-place array manipulation
Asked to do something without extra space (i.e., O(1))
Remove elements, move items, overwrite data
Examples:
removeElement(nums, val)
moveZeroes(nums)
mergeSortedArraysInPlace
🔀 5. Two sorted arrays or ranges
- Problems involving merging, intersections, comparisons between two lists
Examples:
mergeTwoSortedArrays(a, b)
findMedianSortedArrays
intersection of two sorted arrays
🧠 Quick Mnemonic:
"Compare ➡️ Slide ➡️ Shrink ➡️ Merge ➡️ Modify"
If you see these verbs or problems that feel like them, two-pointers might be the answer.
Sliding window
Theory


Maximum sum of a contigious subarray of size 3

smallest sub-array with given sum

Backtracking
Combination Sum problem

Letter Combinations of a phone number

Dynamic programming
Best time to buy stock
String
Longest Palindromic Substring

To be updated ....



