[AI] build roadmap for learning
This commit is contained in:
@@ -0,0 +1,346 @@
|
||||
# Binary Search Pattern
|
||||
|
||||
## Overview
|
||||
Binary search is a fundamental algorithm for finding elements in sorted arrays. It follows the divide-and-conquer strategy, repeatedly dividing the search space in half.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Binary Search Principle
|
||||
- **Precondition**: Array must be sorted
|
||||
- **Process**: Compare target with middle element, eliminate half of search space
|
||||
- **Complexity**: O(log n) time, O(1) space
|
||||
|
||||
### Basic Template
|
||||
```typescript
|
||||
function binarySearch(arr: number[], target: number): number {
|
||||
let left = 0;
|
||||
let right = arr.length - 1;
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
|
||||
if (arr[mid] === target) {
|
||||
return mid;
|
||||
} else if (arr[mid] < target) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1; // Target not found
|
||||
}
|
||||
```
|
||||
|
||||
## Variations
|
||||
|
||||
### 1. Lower Bound (First Occurrence)
|
||||
```typescript
|
||||
function lowerBound(arr: number[], target: number): number {
|
||||
let left = 0;
|
||||
let right = arr.length - 1;
|
||||
let result = -1;
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
|
||||
if (arr[mid] >= target) {
|
||||
result = mid;
|
||||
right = mid - 1;
|
||||
} else {
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Upper Bound (Last Occurrence)
|
||||
```typescript
|
||||
function upperBound(arr: number[], target: number): number {
|
||||
let left = 0;
|
||||
let right = arr.length - 1;
|
||||
let result = -1;
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
|
||||
if (arr[mid] <= target) {
|
||||
result = mid;
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Find Closest Element
|
||||
```typescript
|
||||
function findClosest(arr: number[], target: number): number {
|
||||
let left = 0;
|
||||
let right = arr.length - 1;
|
||||
|
||||
while (left < right - 1) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
|
||||
if (arr[mid] < target) {
|
||||
left = mid;
|
||||
} else {
|
||||
right = mid;
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the two remaining elements
|
||||
return Math.abs(arr[left] - target) <= Math.abs(arr[right] - target)
|
||||
? arr[left] : arr[right];
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced Applications
|
||||
|
||||
### 1. Search in Rotated Sorted Array
|
||||
```typescript
|
||||
function search(nums: number[], target: number): number {
|
||||
let left = 0;
|
||||
let right = nums.length - 1;
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
|
||||
if (nums[mid] === target) {
|
||||
return mid;
|
||||
}
|
||||
|
||||
// Check if left half is sorted
|
||||
if (nums[left] <= nums[mid]) {
|
||||
if (nums[left] <= target && target < nums[mid]) {
|
||||
right = mid - 1;
|
||||
} else {
|
||||
left = mid + 1;
|
||||
}
|
||||
} else {
|
||||
// Right half is sorted
|
||||
if (nums[mid] < target && target <= nums[right]) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Find Minimum in Rotated Sorted Array
|
||||
```typescript
|
||||
function findMin(nums: number[]): number {
|
||||
let left = 0;
|
||||
let right = nums.length - 1;
|
||||
|
||||
while (left < right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
|
||||
if (nums[mid] > nums[right]) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return nums[left];
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Search in 2D Matrix
|
||||
```typescript
|
||||
function searchMatrix(matrix: number[][], target: number): boolean {
|
||||
if (matrix.length === 0 || matrix[0].length === 0) return false;
|
||||
|
||||
const rows = matrix.length;
|
||||
const cols = matrix[0].length;
|
||||
|
||||
let left = 0;
|
||||
let right = rows * cols - 1;
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
const row = Math.floor(mid / cols);
|
||||
const col = mid % cols;
|
||||
|
||||
if (matrix[row][col] === target) {
|
||||
return true;
|
||||
} else if (matrix[row][col] < target) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
## Time Complexity Analysis
|
||||
|
||||
| Problem | Time Complexity | Space Complexity | Notes |
|
||||
|---------|----------------|----------------|---------|
|
||||
| Basic Binary Search | O(log n) | O(1) | Standard implementation |
|
||||
| Lower Bound | O(log n) | O(1) | First occurrence |
|
||||
| Upper Bound | O(log n) | O(1) | Last occurrence |
|
||||
| Rotated Array | O(log n) | O(1) | Handle rotation |
|
||||
| 2D Matrix | O(log(mn)) | O(1) | Treat as 1D |
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Pointer Initialization
|
||||
- Use `left = 0` and `right = arr.length - 1`
|
||||
- For exclusive bounds: `left = 0` and `right = arr.length`
|
||||
|
||||
### 2. Mid Calculation
|
||||
```typescript
|
||||
// Avoid overflow in some languages
|
||||
const mid = left + Math.floor((right - left) / 2);
|
||||
|
||||
// Standard approach in TypeScript
|
||||
const mid = Math.floor((left + right) / 2);
|
||||
```
|
||||
|
||||
### 3. Loop Condition
|
||||
```typescript
|
||||
// Include equal case to find target
|
||||
while (left <= right)
|
||||
|
||||
// For exclusive bounds
|
||||
while (left < right)
|
||||
```
|
||||
|
||||
### 4. Pointer Updates
|
||||
```typescript
|
||||
// Always move mid pointer
|
||||
left = mid + 1; // Not mid
|
||||
right = mid - 1; // Not mid
|
||||
```
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
### 1. Infinite Loop
|
||||
```typescript
|
||||
// Wrong: mid might not move
|
||||
left = mid; // Should be mid + 1
|
||||
right = mid; // Should be mid - 1
|
||||
|
||||
// Correct: move pointers past mid
|
||||
left = mid + 1;
|
||||
right = mid - 1;
|
||||
```
|
||||
|
||||
### 2. Incorrect Mid Calculation
|
||||
```typescript
|
||||
// Wrong: potential overflow
|
||||
const mid = (left + right) / 2;
|
||||
|
||||
// Correct: safer approach
|
||||
const mid = left + Math.floor((right - left) / 2);
|
||||
```
|
||||
|
||||
### 3. Wrong Loop Condition
|
||||
```typescript
|
||||
// Wrong: might miss element
|
||||
while (left < right) {
|
||||
// Target might be at right boundary
|
||||
|
||||
// Correct: include equal case
|
||||
while (left <= right) {
|
||||
// Ensures all elements are checked
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Not Handling Edge Cases
|
||||
```typescript
|
||||
// Wrong: empty array
|
||||
while (left <= right) {
|
||||
// Will fail for empty array
|
||||
|
||||
// Correct: add check
|
||||
if (arr.length === 0) return -1;
|
||||
```
|
||||
|
||||
## Practice Problems
|
||||
|
||||
### Easy
|
||||
- [ ] Basic binary search
|
||||
- [ ] Find lower bound
|
||||
- [ ] Find upper bound
|
||||
- [ ] Find closest element
|
||||
- [ ] Find peak in mountain array
|
||||
|
||||
### Medium
|
||||
- [ ] Search in rotated sorted array
|
||||
- [ ] Find minimum in rotated sorted array
|
||||
- [ ] Search in 2D matrix
|
||||
- [ ] Find first and last position of element
|
||||
- [ ] Find peak element
|
||||
|
||||
### Hard
|
||||
- [ ] Median of two sorted arrays
|
||||
- [ ] Find k-th element in sorted matrix
|
||||
- [ ] Find smallest letter greater than target
|
||||
- [ ] Find in mountain array
|
||||
- [ ] Find frequency of element in sorted array
|
||||
|
||||
## Real-world Applications
|
||||
|
||||
1. **Database Indexes**: B-tree searches
|
||||
2. **Game Development**: Collision detection, spatial partitioning
|
||||
3. **Machine Learning**: Decision trees, feature selection
|
||||
4. **Operating Systems**: Process scheduling, resource allocation
|
||||
|
||||
## Binary Search vs Linear Search
|
||||
|
||||
| Aspect | Binary Search | Linear Search |
|
||||
|--------|---------------|---------------|
|
||||
| Time Complexity | O(log n) | O(n) |
|
||||
| Space Complexity | O(1) | O(1) |
|
||||
| Precondition | Array must be sorted | No precondition |
|
||||
| Best for | Large sorted datasets | Small or unsorted datasets |
|
||||
| Insertion | O(n) | O(1) |
|
||||
|
||||
## Tips for Mastery
|
||||
|
||||
### 1. Understand the Pattern
|
||||
- Binary search works on any monotonic function
|
||||
- It's not just for arrays, but any searchable space
|
||||
- The key is reducing search space by half each time
|
||||
|
||||
### 2. Practice Edge Cases
|
||||
- Empty array
|
||||
- Single element
|
||||
- All elements same
|
||||
- Target not present
|
||||
- Target at boundaries
|
||||
|
||||
### 3. Implement Variations
|
||||
- Practice lower/upper bounds
|
||||
- Work with rotated arrays
|
||||
- Try 2D searches
|
||||
- Implement on custom data structures
|
||||
|
||||
### 4. Combine with Other Patterns
|
||||
- Binary search + two pointers
|
||||
- Binary search + sliding window
|
||||
- Binary search + dynamic programming
|
||||
|
||||
## Next Steps
|
||||
1. Master basic binary search (5+ problems)
|
||||
2. Practice rotated array variations
|
||||
3. Learn to apply binary search to search spaces
|
||||
4. Combine with other algorithmic patterns
|
||||
|
||||
---
|
||||
|
||||
**Key Takeaway**: Binary search is one of the most important algorithms. It's efficient, elegant, and applicable to many problems beyond simple array searches. Always consider binary search when dealing with sorted data.
|
||||
Reference in New Issue
Block a user