0% found this document useful (0 votes)
1 views

Linear and binary searching

The document provides an overview of search algorithms, focusing on Linear and Binary Search techniques. Linear Search checks each item sequentially, making it simple but slower for large datasets, while Binary Search efficiently divides sorted data to locate items quickly. Key comparisons highlight when to use each algorithm based on data size and structure, along with practical coding examples and time complexity analyses.

Uploaded by

bhattdev578
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

Linear and binary searching

The document provides an overview of search algorithms, focusing on Linear and Binary Search techniques. Linear Search checks each item sequentially, making it simple but slower for large datasets, while Binary Search efficiently divides sorted data to locate items quickly. Key comparisons highlight when to use each algorithm based on data size and structure, along with practical coding examples and time complexity analyses.

Uploaded by

bhattdev578
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Lecture Notes

1. Introduction
Every day, we sift through massive amounts of information—whether we’re searching for a file in our
computer’s folders, finding an email in our inbox, or looking up a product on an e-commerce website.
Searching is so fundamental that without efficient ways to find what we need, working with large sets
of data would be painfully slow and complicated.

In software and algorithmic design, we often talk about search algorithms—instructions for how a
computer locates a specific piece of data quickly in a collection. Two of the most common are:

Linear Search: A simple method, checking one item at a time.


Binary Search: An efficient technique that repeatedly divides the data in half to zero in on what
you’re looking for.

Real-World Relevance:

E-commerce: Searching for products among thousands or millions of items.


Databases: Locating a record among massive datasets.
Search Engines: Large-scale searching of billions of web pages.
Coding Interviews: Search algorithms are foundational and commonly tested.

Understanding these methods will give you a solid base for more advanced concepts in data
structures and algorithms—like sorting, graph traversal, and even machine learning techniques. Let’s
begin with the more straightforward Linear Search, then compare it to the more powerful Binary
Search.
2. Linear Search

2.1 Overview of Linear Search


Definition: Linear Search (also known as sequential search) involves scanning each element of a list
or array one by one, starting from the first and moving toward the last, until:

We find the target element, or


We exhaust the list without finding it.

If you imagine having a shoebox full of index cards—each card has a word, and you want to find a
specific word. You’d pick the first card, check it, then move on to the second card, and so on. This is
effectively the process of Linear Search.

Why it’s useful:

Very easy to understand.


Can be implemented quickly.
Works on any unsorted or sorted data (though it doesn’t exploit any extra structure from sorted
data).

2.2 Real-Life Analogies


1. Finding Keys in a Drawer
Suppose you have a drawer filled with various items in no particular order. You dig through the
drawer item by item, from top to bottom or front to back, until you spot your keys.
2. Checking Attendance
A teacher calls names from a list of students in alphabetical order, but the teacher wants to check
if “Alex” is in the class. They might read name after name until they arrive at Alex.
3. Unorganized Book Stack
You have a stack of books on your desk with no logical arrangement. To find a particular title, you
lift each book in sequence, checking if it matches the one you want.

In each case, you only finish searching once you’ve encountered the desired item or confirmed it isn’t
there.
2.3 Detailed Code Example (Python)

def linear_search(arr, x):


"""
Performs a linear (sequential) search for element x in arr.
Returns the index of x if found, otherwise returns -1.
"""
for i in range(len(arr)):
# Compare the current element with x
if arr[i] == x:
return i # Found x at index i
return -1 # If we finish the loop, x is not present

Step-by-Step Explanation:

1. Function Definition: linear_search(arr, x) indicates that we’ll pass an array (or list) arr and
the element x we’re searching for.
2. Loop: We iterate i from 0 up to (length of arr - 1).
3. Check: At each position, compare arr[i] with x .
4. Return: If they match, immediately return the index i .
5. Not Found: If the loop finishes without finding a match, return -1 .

2.4 Time Complexity Analysis

Best Case (O(1))


The target is right at the start of the list.
Example: Searching for 4 in [4, 9, 3, 1, ...] ; we find it on the first comparison.

Worst Case (O(n))


The target is at the very end or not even in the list.
We have to compare every element once.
For n elements, that’s n comparisons.

Average Case (O(n))


On average, if the target is equally likely to appear anywhere, you might search about half the list
before finding it (but in Big-O terms, it’s still O(n)).
Key Takeaway: For large n , linear search can become slow, since it can do as many as n
comparisons.

2.5 Space Complexity


Aside from the index counter, we don’t use additional significant space.
Space Complexity = O(1).

2.6 “Key Points to Remember” for Linear Search


Universal: Works on both sorted and unsorted data.
Easy to Implement: Just compare each item one by one.
Time Complexity: O(n) in the worst case.
Space Complexity: O(1).
Practical Tip: If you only search once in a small dataset or rarely search at all, Linear Search is
often sufficient.

2.7 Trick Questions and Answers


1. Question: “My list is already large, and I only need to check for an item once. Should I sort it first
and then use Binary Search?”
Answer: Probably no. Sorting will take O(n log n). A single linear search is O(n). If you only
do one search, it’s more efficient to stick with Linear Search.
2. Question: “Is there a scenario in which Linear Search could beat Binary Search for sorted data?”
Answer: Yes, if the target is always near the front (e.g., 1st or 2nd element). In that case,
Linear Search might find the answer in O(1) time, which is effectively faster. However,
generally if you have many searches over large data, Binary Search is still better in the
average sense.
3. Binary Search

3.1 Overview of Binary Search


When data is sorted, we can do far better than scanning every element. Binary Search cleverly
eliminates half of the data with each comparison:

1. Check the middle element of the array.


2. If it’s the target, we’re done.
3. If it’s larger than the target, we only search the left half.
4. If it’s smaller than the target, we only search the right half.

This approach quickly shrinks the search area until the target is found or until there’s nowhere left to
search.

Important Note: Binary Search requires sorted data. If the data is not sorted, the algorithm’s logic will
fail, as looking “left” or “right” no longer reliably moves closer to or further from the target.

3.2 Real-Life Analogies


1. Dictionary or Phone Book
When searching for a word in a dictionary, you don’t start at the first page and read every
definition. You open near the middle, compare the alphabetical position, and decide which
half of the dictionary to focus on next.
2. Number Guessing Game
Someone thinks of a number between 1 and 100. You guess 50, and they say “too high” or
“too low.” Instantly, you cut the possibilities in half—either look between 1 and 49 or between
51 and 100.
3. Binary Divide-and-Conquer
Imagine you’re trying to locate a friend in a large city block that’s fully sorted by house
numbers. Rather than knocking on every door, you can jump to the middle house number and
decide if you need to look in lower or higher addresses.
3.3 Detailed Code Example (Python, Iterative
Approach)

def binary_search(arr, x):


"""
Searches for element x in a sorted list arr using Binary Search.
Returns the index of x if found, otherwise returns -1.
"""
left = 0 # Start index
right = len(arr) - 1 # End index

while left <= right:


mid = (left + right) // 2 # Find the midpoint

if arr[mid] == x:
return mid # Found the target
elif arr[mid] > x:
right = mid - 1 # Eliminate the right half
else:
left = mid + 1 # Eliminate the left half

return -1 # If not found

Step-by-Step Explanation:

1. Initialization: left points to the start (index 0), and right points to the end (index len(arr)-1 ).
2. Loop Condition: While there’s a valid range ( left <= right ), keep narrowing.
3. Mid Calculation: We use (left + right) // 2 to get the middle index.
4. Comparison:
If arr[mid] is the target x , we’re done.
If arr[mid] is greater than x , we move right to mid-1 .
Otherwise, we move left to mid+1 .
5. No Match: If the loop exits, the element is not present.
3.4 Recursive Version (Python)

def binary_search_recursive(arr, left, right, x):


"""
Recursive version of Binary Search.
arr: sorted list
left, right: bounds of the current search segment
x: the target element
"""
if left > right:
return -1 # Base condition: no range left to search

mid = (left + right) // 2

if arr[mid] == x:
return mid
elif arr[mid] > x:
return binary_search_recursive(arr, left, mid - 1, x)
else:
return binary_search_recursive(arr, mid + 1, right, x)

Space Complexity for recursion is O(log n) due to the call stack.


The functionality is the same, but some people find it more intuitive.

3.5 Time Complexity Analysis


Best Case: O(1). If the target is exactly at the middle on the first check.
Worst Case: O(log n). Each comparison halves the search space, so the maximum number of
comparisons is proportional to log2(n) .
Average Case: Also O(log n), because on average, each step splits the search range in half, just
like the worst case.

Big-O Notation Reminder: O(log n) grows very slowly compared to O(n) . For example, if
n = 1,000,000 , log2(n) is just about 20.

3.6 Space Complexity


Iterative Approach: O(1), aside from a few variables ( left , right , mid ).
Recursive Approach: O(log n) due to the depth of the recursive calls.
3.7 “Key Points to Remember” for Binary Search
Requires Sorting: If the list isn’t sorted, don’t use Binary Search.
Very Efficient: O(log n) is much faster than O(n) for large data sizes.
Two Approaches: Iterative (commonly used in production) or recursive (easier to conceptualize).
Practical Tip: When you have large sorted datasets and you’re searching frequently, Binary
Search is usually the way to go.

3.8 Trick Questions and Answers


1. Question: “What happens if I use Binary Search on data that’s not sorted?”
Answer: The algorithm won’t work correctly. You might skip areas where the target actually is
and end up with a wrong answer or -1 .
2. Question: “If my data is partially sorted or has some pattern, can I still use Binary Search?”
Answer: You need a fully sorted range for the basic Binary Search. However, specialized
algorithms like Interpolation Search or Exponential Search might exploit certain patterns—
but that’s more advanced.
3. Question: “Does it matter if the array has duplicates?”
Answer: You can still use Binary Search. If duplicates exist, you might find any one of the
matching positions. For unique identification of duplicates, modifications are needed, but the
basic approach still applies.

4. Comparing Linear vs. Binary Search


A quick comparison can help you decide which algorithm suits your situation.

Time Space Requires Real-World


Algorithm Concept
Complexity Complexity Sorting? Use Case

- Small lists
Check each - Rarely
Linear item one by one searching data
O(n) O(1) No
Search until found/not - Data easily
found accessed
sequentially
Time Space Requires Real-World
Algorithm Concept
Complexity Complexity Sorting? Use Case

- Large
Repeatedly datasets
divide the - Frequent
Binary O(1) iter.
(sorted) list in O(log n) Yes searches
Search O(log n) rec.
half for each - Scenarios
step where data is
already sorted

Additional Tips
1. Sorted Data: If you have to sort the data anyway, consider the cost of sorting (O(n log n)) plus the
repeated advantage of O(log n) lookups if you’ll search multiple times.
2. Memory Constraints: Both are typically O(1) extra memory in their iterative forms, so not a big
difference there.
3. Data Location: If your data structure is not conducive to random access (e.g., linked lists),
Binary Search loses its advantage because you can’t jump to the midpoint in constant time.

5. Extended “Key Points to Remember”


1. Linear Search
Works on any data arrangement.
Simplicity is its main virtue.
Worst-case scenario involves checking every element.
2. Binary Search
Requires a pre-sorted dataset.
Powerful in large collections, with O(log n) performance.
Get comfortable with the concept of halving the problem to reduce computational steps.
3. When to Use Which
Few, rare searches in unsorted data → Linear Search.
Repeated, frequent searches in sorted data → Binary Search.
6. In-Depth Trick Questions and Answers
These questions dig deeper into design considerations:

1. Q: "I have an unsorted list of size 10 million, and I plan to do hundreds of searches. Should I sort
the list first or just do linear searches for each query?"
A: Sorting once costs O(n log n). For 10 million items, that can be quite big, but if you then do
hundreds or thousands of searches using Binary Search at O(log n) each, the total might be
less than doing linear searches (which would be O(n) for every search). You have to weigh
the cost of sorting versus the sum of repeated searches.
2. Q: "How does Binary Search handle data that changes frequently (e.g., new elements constantly
being added or updated)?"
A: If the data is constantly changing (thus losing its sorted order), you’d have to re-sort
(costly!) or adopt a data structure (like a balanced binary search tree) that keeps elements
in sorted order as you insert or remove items. The standard Binary Search only works on
sorted, static (or rarely updated) lists.
3. Q: "Which algorithm is better for searching in a linked list?"
A: For a singly linked list, you don’t have direct access to the middle element in O(1) time. So
even if it’s sorted, you can’t easily jump to the midpoint. Typically, Linear Search is used
unless you have a specialized data structure (like a skip list).

7. At a Glance (Quick Reference)


Here is a concise summary to keep handy:

1. Linear Search
Definition: Check each element in turn.
Time: O(n).
Space: O(1).
Use When: Unsorted data, small lists, minimal searching.
2. Binary Search
Definition: Divide and conquer; check the middle of a sorted list.
Time: O(log n).
Space: O(1) iterative, O(log n) recursive.
Use When: Large sorted data, repeated searches.
8. Practical Exercise

8.1 Exercise Description


Write a combined program that:

1. Takes an array of integers from the user.


2. Takes a target integer to search for.
3. Asks the user if they want to sort the array first or not.
4. If they choose “sort,” the program sorts the array and performs Binary Search.
5. Otherwise, it performs Linear Search.

Goal: Observe how sorting once and searching many times might be beneficial compared to just
searching linearly.

8.2 Example Walkthrough


1. User inputs:
arr = [7, 2, 13, 1, 9, 5]
x = 13
Choice: “yes” (to sort)
2. The program sorts the list: [1, 2, 5, 7, 9, 13]
3. Then applies Binary Search to find 13 , which is now the last element.
4. Result: Found at index 5 .

If the user had answered “no,” the program would do a Linear Search directly on
[7, 2, 13, 1, 9, 5] , checking each item in sequence.
8.3 Starter Code Snippet (Python)

def search_comparison_program():
# Step 1: Gather data
arr_str = input("Enter integers separated by spaces: ")
arr = list(map(int, arr_str.split()))

x = int(input("Enter the target integer: "))

# Step 2: Ask if user wants to sort


choice = input("Do you want to sort the list? (yes/no): ").strip().lower()

if choice == 'yes':
# Sort the array
arr.sort()
print("The list after sorting:", arr)
print("Performing Binary Search...")
result = binary_search(arr, x) # Use the iterative version
else:
print("Performing Linear Search on the unsorted list...")
result = linear_search(arr, x)

# Step 3: Output result


if result == -1:
print(f"Element {x} not found in the list.")
else:
print(f"Element {x} found at index: {result}")

Explanation:

Line 2–4: Reads user input and converts it to a list of integers.


Line 6: Reads the target integer.
Line 9: Asks if user wants to sort.
Line 11–14: If “yes,” sorts the list in ascending order and calls binary_search .
Line 16–17: If “no,” calls linear_search on the unsorted list.
Line 20–23: Prints the outcome of the search.

8.4 Brief Solution Explanation


You compare how quickly the search works, especially for large inputs.
For a single search, sorting might or might not be beneficial.
If you plan multiple searches over the same data, sorting once (O(n log n)) then using repeated
Binary Searches (O(log n) each) is often a win.

End of Notes
You now have a comprehensive foundation in two major searching algorithms. Feel free to
experiment with your own data, track the number of comparisons or steps it takes, and see how these
algorithms perform in practice. Happy coding!

You might also like