Back to Welcome Page

Module 3: Searching

Master the fundamentals of searching algorithms. Learn how to implement and analyze searching algorithms.

Module Objectives

Upon completion of this module you will be able to:

Linear Search

Understanding Linear Search

Linear search is the simplest search algorithm. It sequentially checks each element in a collection until the target is found or the collection is exhausted.

// Linear search implementation function linearSearch(arr, target) { for (let i = 0; i < arr.length; i++) { if (arr[i] === target) { return i; // Return the index where target is found } } return -1; // Return -1 if target is not found } // Example usage const numbers = [10, 24, 56, 7, 89, 42, 13]; console.log(linearSearch(numbers, 89)); // 4 console.log(linearSearch(numbers, 100)); // -1

Time Complexity:

Space Complexity: O(1) - Uses a constant amount of extra space

Advantages of Linear Search:

Disadvantages:

Optimized Linear Search

We can optimize linear search by adding early termination conditions or implementing search strategies like the sentinel search:

// Linear search with sentinel function sentinelLinearSearch(arr, target) { const n = arr.length; // Save the last element const last = arr[n - 1]; // Place the target as sentinel at the end arr[n - 1] = target; let i = 0; // The loop will always terminate because target is in the array while (arr[i] !== target) { i++; } // Restore the original last element arr[n - 1] = last; // Check if we found the target or just the sentinel if (i < n - 1 || last === target) { return i; } return -1; }

Binary Search

Understanding Binary Search

Binary search is a divide-and-conquer algorithm that efficiently finds a target value in a sorted array. It repeatedly divides the search space in half, eliminating half of the remaining elements at each step.

// Binary search implementation (iterative) function binarySearch(arr, target) { let left = 0; let right = arr.length - 1; while (left <= right) { // Calculate middle index (avoid overflow) const mid = left + Math.floor((right - left) / 2); // Check if target is at mid if (arr[mid] === target) { return mid; } // If target is greater, ignore left half if (arr[mid] < target) { left = mid + 1; } // If target is smaller, ignore right half else { right = mid - 1; } } // Target not found return -1; } // Example usage const sortedNumbers = [2, 5, 8, 12, 16, 23, 38, 56, 72, 91]; console.log(binarySearch(sortedNumbers, 23)); // 5 console.log(binarySearch(sortedNumbers, 25)); // -1

Recursive Binary Search

Binary search can also be implemented recursively:

// Binary search implementation (recursive) function binarySearchRecursive(arr, target, left = 0, right = arr.length - 1) { // Base case: element not found if (left > right) { return -1; } // Calculate middle index const mid = left + Math.floor((right - left) / 2); // Check if target is at mid if (arr[mid] === target) { return mid; } // Recursive cases if (arr[mid] < target) { // Search right half return binarySearchRecursive(arr, target, mid + 1, right); } else { // Search left half return binarySearchRecursive(arr, target, left, mid - 1); } }

Time Complexity:

Space Complexity:

Advantages of Binary Search:

Disadvantages:

Comparison: Linear vs. Binary Search

Aspect Linear Search Binary Search
Time Complexity O(n) O(log n)
Data Requirement Works on sorted or unsorted data Requires sorted data
Best For Small datasets, unsorted data Large datasets, sorted data
Implementation Simple More complex
Data Structure Works with arrays and linked lists Requires random access (arrays)

Practical Example: Searching in a phonebook

For a phonebook with 1000 pages:

Practice with LeetCode Problems

Note: Previously, this course referenced the CodeSignal Arcade for practice, which is no longer available. The LeetCode problems below follow the same principles and are an excellent alternative for practicing search algorithms.

Linear Search Problems:

Binary Search Problems: