Skip to content

Commit a2656bd

Browse files
authored
Enhance searching algorithms documentation
Updated explanations and formatting for linear search, sentinel search, binary search, ternary search, and jump search in the notes.
1 parent 35f67bf commit a2656bd

File tree

1 file changed

+185
-80
lines changed

1 file changed

+185
-80
lines changed

notes/searching.md

Lines changed: 185 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -40,42 +40,66 @@ $$
4040
\text{Output: } \text{not found}
4141
$$
4242

43-
**How it works**
43+
**How Linear Search Works**
44+
45+
We start at index `0`, compare the value with the target, and keep moving right until we either **find it** or reach the **end**.
4446

45-
Start at index 0, compare, move right; stop on first equal or after the last element.
47+
Target **5** in `[7, 3, 5, 2, 9]`
4648

4749
```
48-
Indexes: 0 1 2 3 4
49-
List: [ 7 ][ 3 ][ 5 ][ 2 ][ 9 ]
50+
Indexes: 0 1 2 3 4
51+
List: [7] [3] [5] [2] [9]
5052
Target: 5
53+
```
5154

52-
Pass 1: pointer at 0 → compare 7 vs 5 → no
53-
v
54-
Indexes: 0 1 2 3 4
55-
|
56-
List: 7 3 5 2 9
55+
*Step 1:* pointer at index 0
5756

58-
Pass 2: pointer at 1 → compare 3 vs 5 → no
59-
v
60-
Indexes: 0 1 2 3 4
61-
|
62-
List: 7 3 5 2 9
57+
```
58+
|
59+
v
60+
7 3 5 2 9
6361
64-
Pass 3: pointer at 2 → compare 5 vs 5 → YES → return 2
65-
v
66-
Indexes: 0 1 2 3 4
67-
|
68-
List: 7 3 5 2 9
62+
→ compare 7 vs 5 → no
6963
```
7064

71-
**Worst case (not found):** you compare every element and then stop.
65+
*Step 2:* pointer moves to index 1
66+
67+
```
68+
|
69+
v
70+
7 3 5 2 9
7271
72+
→ compare 3 vs 5 → no
7373
```
74-
Indexes: 0 1 2
75-
List: [ 1 ][ 2 ][ 3 ]
74+
75+
*Step 3:* pointer moves to index 2
76+
77+
```
78+
|
79+
v
80+
7 3 5 2 9
81+
82+
→ compare 5 vs 5 → YES ✅ → return index 2
83+
```
84+
85+
**Worst Case (Not Found)**
86+
87+
Target **9** in `[1, 2, 3]`
88+
89+
```
90+
Indexes: 0 1 2
91+
List: [1] [2] [3]
7692
Target: 9
93+
```
7794

78-
Checks: (1≠9) → (2≠9) → (3≠9) → end → not found
95+
Checks:
96+
97+
```
98+
→ 1 ≠ 9
99+
→ 2 ≠ 9
100+
→ 3 ≠ 9
101+
→ end
102+
→ not found ❌
79103
```
80104

81105
* Works on any list; no sorting or structure required.
@@ -116,40 +140,55 @@ $$
116140

117141
Put the target at one extra slot at the end so the loop is guaranteed to stop on a match; afterward, check whether the match was inside the original range.
118142

143+
Target **11** not in the list
144+
119145
```
120-
Original length n = 5
121-
Before: [ 4 ][ 9 ][ 1 ][ 7 ][ 6 ]
146+
Original list (n=5):
147+
[ 4 ][ 9 ][ 1 ][ 7 ][ 6 ]
122148
Target: 11
149+
```
123150

124151
Add sentinel (extra slot):
125-
[ 4 ][ 9 ][ 1 ][ 7 ][ 6 ][ 11 ]
126-
Indexes: 0 1 2 3 4 5 ← sentinel position
127152

128-
Scan left→right until you see 11:
153+
```
154+
[ 4 ][ 9 ][ 1 ][ 7 ][ 6 ][ 11 ]
155+
0 1 2 3 4 5 ← sentinel
156+
```
129157

130-
Step 1: 4 ≠ 11
131-
^
132-
Step 2: 9 ≠ 11
133-
^
134-
Step 3: 1 ≠ 11
135-
^
136-
Step 4: 7 ≠ 11
137-
^
138-
Step 5: 6 ≠ 11
139-
^
140-
Step 6: 11 (match at index 5, which is the sentinel)
158+
Scan step by step:
141159

142-
Because the first match is at index 5 (the sentinel position), the target was not in the original indexes 0..4 → report “not found”.
143160
```
161+
4 ≠ 11 → pointer at 0
162+
9 ≠ 11 → pointer at 1
163+
1 ≠ 11 → pointer at 2
164+
7 ≠ 11 → pointer at 3
165+
6 ≠ 11 → pointer at 4
166+
11 = 11 → pointer at 5 (sentinel)
167+
```
168+
169+
Therefore, **not found** in original list.
144170

145-
**When the target exists inside the list:**
171+
Target **6** inside the list
146172

147173
```
148-
List: [ 12 ][ 8 ][ 6 ][ 15 ] n = 4
174+
Original list (n=4):
175+
[ 12 ][ 8 ][ 6 ][ 15 ]
149176
Target: 6
150-
With sentinel: [ 12 ][ 8 ][ 6 ][ 15 ][ 6 ]
177+
```
178+
179+
Add sentinel:
180+
181+
```
182+
[ 12 ][ 8 ][ 6 ][ 15 ][ 6 ]
183+
0 1 2 3 4
184+
```
185+
186+
Scan:
151187

152-
Scan: 12≠6 → 8≠6 → 6=6 (index 2 < n) → real match at 2
188+
```
189+
12 ≠ 6 → index 0
190+
8 ≠ 6 → index 1
191+
6 = 6 → index 2 ✅
153192
```
154193

155194
* Removes the per-iteration “have we reached the end?” check; the sentinel guarantees termination.
@@ -198,28 +237,61 @@ $$
198237
\text{Output: } \text{not found}
199238
$$
200239

201-
202240
**How it works**
203241

242+
We repeatedly check the **middle** element, and then discard half the list based on comparison.
243+
244+
Find **16** in:
245+
246+
```
247+
A = [ 2 ][ 5 ][ 8 ][ 12 ][ 16 ][ 23 ][ 38 ]
248+
i = 0 1 2 3 4 5 6
204249
```
205-
Sorted A: [ 2 ][ 5 ][ 8 ][12 ][16 ][23 ][38 ]
206-
Indexes: 0 1 2 3 4 5 6
207-
Target: 16
208250

209-
1) low=0, high=6 → mid=(0+6)//2=3
210-
A[3]=12 < 16 → discard left half up to mid, keep [mid+1..high]
211-
[ 2 ][ 5 ][ 8 ] |[12 ]| [16 ][23 ][38 ]
212-
low=4 high=6
251+
*Step 1*
213252

214-
2) low=4, high=6 → mid=(4+6)//2=5
215-
A[5]=23 > 16 → discard right half after mid, keep [low..mid-1]
216-
[16 ][23 ]|[38 ]
217-
low=4 high=4
253+
```
254+
low = 0, high = 6
255+
mid = (0+6)//2 = 3
256+
A[3] = 12 < 16 → target is to the RIGHT → new low = mid + 1 = 4
257+
258+
A = [ 2 ][ 5 ][ 8 ][ 12 ][ 16 ][ 23 ][ 38 ]
259+
i = 0 1 2 3 4 5 6
260+
↑L ↑M ↑H
261+
0 3 6
262+
Active range: indices 0..6
263+
```
218264

219-
3) low=4, high=4 → mid=4
220-
A[4]=16 = target → FOUND at index 4
265+
*Step 2*
266+
267+
```
268+
low = 4, high = 6
269+
mid = (4+6)//2 = 5
270+
A[5] = 23 > 16 → target is to the LEFT → new high = mid - 1 = 4
271+
272+
A = [ 2 ][ 5 ][ 8 ][ 12 ][ 16 ][ 23 ][ 38 ]
273+
i = 0 1 2 3 4 5 6
274+
↑L ↑M ↑H
275+
4 5 6
276+
Active range: indices 4..6
221277
```
222278

279+
*Step 3*
280+
281+
```
282+
low = 4, high = 4
283+
mid = 4
284+
A[4] = 16 == target ✅
285+
286+
A = [ 2 ][ 5 ][ 8 ][ 12 ][ 16 ][ 23 ][ 38 ]
287+
i = 0 1 2 3 4 5 6
288+
↑LMH
289+
4
290+
Active range: indices 4..4
291+
```
292+
293+
FOUND at index 4
294+
223295
* Requires a sorted array (assume ascending here).
224296
* Time: O(log n); Space: O(1) iterative.
225297
* Returns any one matching index by default; “first/last occurrence” is a small, common refinement.
@@ -253,25 +325,37 @@ $$
253325

254326
**How it works**
255327

328+
We divide the array into **three parts** using two midpoints `m1` and `m2`.
329+
330+
* If `target < A[m1]` → search $[low .. m1-1]$
331+
* Else if `target > A[m2]` → search $[m2+1 .. high]$
332+
* Else → search $[m1+1 .. m2-1]$
333+
256334
```
257-
Sorted A: [ 1 ][ 4 ][ 7 ][ 9 ][12 ][15 ]
258-
Indexes: 0 1 2 3 4 5
335+
A = [ 1 ][ 4 ][ 7 ][ 9 ][ 12 ][ 15 ]
336+
i = 0 1 2 3 4 5
259337
Target: 9
338+
```
260339

261-
1) low=0, high=5
262-
m1 = low + (high-low)//3 = 0 + 5//3 = 1
263-
m2 = high - (high-low)//3 = 5 - 5//3 = 3
340+
*Step 1*
264341

265-
Compare A[m1]=4, A[m2]=9 with target=9:
342+
```
343+
low = 0, high = 5
344+
345+
m1 = low + (high - low)//3 = 0 + (5)//3 = 1
346+
m2 = high - (high - low)//3 = 5 - (5)//3 = 3
266347
267-
A[m2]=9 = target → FOUND at index 3
348+
A[m1] = 4
349+
A[m2] = 9
268350
269-
(If no immediate match:)
270-
- If target < A[m1], keep [low..m1-1]
271-
- Else if target > A[m2], keep [m2+1..high]
272-
- Else keep [m1+1..m2-1] and repeat
351+
A = [ 1 ][ 4 ][ 7 ][ 9 ][ 12 ][ 15 ]
352+
i = 0 1 2 3 4 5
353+
↑L ↑m1 ↑m2 ↑H
354+
0 1 3 5
273355
```
274356

357+
FOUND at index 3
358+
275359
* Also assumes a sorted array.
276360
* For discrete sorted arrays, it does **not** beat binary search asymptotically; it performs more comparisons per step.
277361
* Most valuable for searching the extremum of a **unimodal function** on a continuous domain; for arrays, prefer binary search.
@@ -304,21 +388,42 @@ $$
304388

305389
**How it works**
306390

391+
Perfect — that’s a **jump search trace**. Let me reformat and polish it so the steps are crystal clear and the “jump + linear scan” pattern pops visually:
392+
393+
We’re applying **jump search** to find $25$ in
394+
395+
$$
396+
A = [1, 4, 9, 16, 25, 36, 49]
397+
$$
398+
399+
with $n=7$, block size $\approx \sqrt{7} \approx 2$, so **jump=2**.
400+
401+
We probe every 2nd index:
402+
403+
* probe = 0 → $A[0] = 1 < 25$ → jump to 2
404+
* probe = 2 → $A[2] = 9 < 25$ → jump to 4
405+
* probe = 4 → $A[4] = 25 \geq 25$ → stop
406+
407+
So target is in block $(2..4]$.
408+
307409
```
308-
Sorted A: [ 1 ][ 4 ][ 9 ][16 ][25 ][36 ][49 ]
309-
Indexes: 0 1 2 3 4 5 6
310-
Target: 25
311-
Choose block size ≈ √n → here n=7 → jump=2
410+
[ 1 ][ 4 ] | [ 9 ][16 ] | [25 ][36 ] | [49 ]
411+
^ ^ ^ ^
412+
probe=0 probe=2 probe=4 probe=6
413+
```
414+
415+
Linear Scan in block (indexes 3..4)
312416

313-
Jumps (probe at 0,2,4,6 until A[probe] ≥ target):
314-
- probe=0 → A[0]=1 (<25) → next probe=2
315-
- probe=2 → A[2]=9 (<25) → next probe=4
316-
- probe=4 → A[4]=25 (≥25) → target must be in block (2..4]
417+
* i = 3 → $A[3] = 16 < 25$
418+
* i = 4 → $A[4] = 25 = 25$ ✅ FOUND
317419

318-
Linear scan inside last block (indexes 3..4):
319-
- i=3 → A[3]=16 (<25)
320-
- i=4 → A[4]=25 (=) FOUND at index 4
321420
```
421+
Block [16 ][25 ]
422+
^ ^
423+
i=3 i=4 (found!)
424+
```
425+
426+
The element $25$ is found at **index 4**.
322427

323428
* Works on sorted arrays; pick jump ≈ √n for good balance.
324429
* Time: O(√n) comparisons on average; Space: O(1).

0 commit comments

Comments
 (0)