Searching and Sorting Algorithms - Chapter 11 Flashcards
Blank is a search algorithm that starts from the beginning of a list, and checks each element until the search key is found or the end of the list is reached.
Linear search
An algorithm’s blank is the time the algorithm takes to execute. If each comparison takes 1 µs (1 microsecond), a linear search algorithm’s runtime is up to 1 second to search a list with 1million elements, 10 s for 10million elements, and so on. Ex: Searching Amazon’s online store, which has more than 200 million items, could require more than 3 minutes.
runtime
An algorithm typically uses a number of steps proportional to the size of the input. For a list with 32 elements, linear search requires at most blank comparisons
32
Blank checks the middle contact first. If the desired contact comes alphabetically before the middle contact, binary search will then search the first half and otherwise the last half. Each step reduces the contacts that need to be searched by half.
binary search,
Blank is a faster algorithm for searching a list if the list’s elements are sorted and directly accessible. Binary search first checks the middle element of the list. If the search key is found, the algorithm returns the matching location. If the search key is not found, the algorithm repeats the search on the remaining left sublist (if the search key was less than the middle element) or the remaining right sublist (if the search key was greater than the middle element).
Binary search
In binary search, for an N element list, the maximum number of steps required to reduce the search space to an empty sublist is blank
floor(log2 N) + 1
Python has a special blank operator, //, that automatically drops the quotient’s decimal portion, so this operator is used when calculating the middle index: mid = (high + low) // 2.
floor division
A blank is an operation that, for a given processor, always operates in the same amount of time, regardless of input values.
constant time operation
In practice, designing an efficient algorithm aims to lower the amount of time that an algorithm runs. However, a single algorithm can always execute more quickly on a faster processor. Therefore, the theoretical analysis of an algorithm describes runtime in terms of number of blank, not nanoseconds.
constant time operations
The blank being used, as well as the blank running the code, both affect what is and what is not a constant time operation.
programming language
hardware
Common constant time operations
Addition, subtraction, multiplication, and division of fixed size integer or floating point values
Assignment of a reference, pointer, or other fixed size data value.
Comparison of two fixed size data values.
Read or write an array element at a particular index.
An algorithm with runtime complexity T(N) has a blank and blank.
lower bound and an upper bound
Blank A function f(N) that is ≤ the best case T(N), for all values of N ≥ 1.
Lower bound:
Blank: A function f(N) that is ≥ the worst case T(N), for all values of N ≥ 1.
Upper bound
Given a function T(N), an blank of lower bounds and upper bounds exist. Ex: If an algorithm’s best case runtime is T(N) = 5N + 4, then subtracting any nonnegative integer yields a lower bound: 5N + 3, 5N + 2, and so on.
infinite number
Two additional criteria are commonly used to choose a preferred upper or lower bound. The preferred bound:
is a single-term polynomial and
bounds T(N) as tightly as possible.
Blank is the classification of runtime complexity that uses functions that indicate only the growth rate of a bounding function.
Asymptotic notation
Three asymptotic notations are commonly used in complexity analysis:
O notation
Ω notation
Θ notation provides a growth rate that is both an upper and lower bound.
Blank provides a growth rate for an algorithm’s upper bound.
O notation
Blank provides a growth rate for an algorithm’s lower bound.
Ω notation
Blank provides a growth rate that is both an upper and lower bound.
Θ notation
Blank is a mathematical way of describing how a function (running time, or runtime, of an algorithm) behaves in relation to the input size.
Big O notation
In Big O notation, all functions that have the same growth rate (as determined by the highest order term) are characterized using the same Big O notation. In essence, all functions that have the same growth rate are considered blank in Big O notation.
equivalent
Given a function that describes the runtime of an algorithm, the Big O notation for that function can be determined using the following rules
If f(x) is a sum of several terms, the highest order term (the one with the fastest growth rate) is kept and others are discarded.
If f(x) has a term that is a product of several factors, all constants (those that are not in terms of x) are omitted.
c · O(f(x)) Big O notation
O(f(x))
c + O(f(x)) Big O notation
O(f(x))
g(x) · O(f(x)) Big O notation
O(g(x)·O(f(x)))
g(x) + O(f(x)) Big O notation
O(g(x) + O(f(x)))
One consideration in evaluating algorithms is that the efficiency of the algorithm is most critical for blank. Small inputs are likely to result in fast runtimes because N is small, so efficiency is less of a concern.
large input sizes
O(1) Name
Constant
O-type
def find_min(x, y):
if x < y:
return x
else:
return y
O(1) Constant
O(log N) Name
Logarithmic
O-type
def binary_search(numbers, key):
low = 0
high = len(numbers) - 1
while high >= low:
mid = (high + low) // 2
if numbers[mid] < key:
low = mid + 1
elif numbers[mid] > key:
high = mid - 1
else:
return mid
return -1 # not found
O(log N or Logarithmic
O(N) name
Linear
O type -
def linear_search(numbers, key):
for i in range(len(numbers)):
if numbers[i] == key:
return i
return -1 # not found
O(N) or Linear
O(N log N) name
Log-linear
O type -
def merge_sort(numbers, i, k):
if i < k:
j = (i + k) // 2 # Find midpoint
merge_sort(numbers, i, j) # Sort left part
merge_sort(numbers, j + 1, k) # Sort right part
merge(numbers, i, j, k) # Merge parts
O(N log N) or Log-linear
O(N^2) name
Quadratic
O type -
def selection_sort(numbers):
for i in range(len(numbers)):
index_smallest = i
for j in range(i + 1, len(numbers)):
if numbers[j] < numbers[index_smallest]:
index_smallest = j
temp = numbers[i] numbers[i] = numbers[index_smallest] numbers[index_smallest] = temp
O(N^2) or Quadratic
O(c^n) Name
Exponential
O type -
def fibonacci(N):
if (1 == N) or (2 == N):
return N
return fibonacci(N-1) + fibonacci(N-2)
O(c^n) or Exponential
To analyze how runtime of an algorithm scales as the input size increases, we first determine how many operations the algorithm executes for a specific input size, N. Then, the blank for that function is determined. Algorithm runtime analysis often focuses on the worst-case runtime complexity.
big-O notation
The blank of an algorithm is the runtime complexity for an input that results in the longest execution. Other runtime analyses include best-case runtime and average-case runtime. Determining the average-case runtime requires knowledge of the statistical properties of the expected data inputs.
worst-case runtime
Since constants are omitted in big-O notation, any constant number of constant time operations is blank.
O(1)
Runtime analysis for blank requires summing the runtime of the inner loop over each outer loop iteration.
nested loops
Blank is typically measured by the algorithm’s computational complexity.
Algorithm efficiency
Blank is the amount of resources used by the algorithm.
Computational complexity
The most common resources considered for computational complexity are the blank and blank.
runtime and memory usage
An algorithm’s blank is a function, T(N), that represents the number of constant time operations performed by the algorithm on an input of size N.
runtime complexity
An algorithm’s blank is the scenario where the algorithm does the minimum possible number of operations.
best case
An algorithm’s blank is the scenario where the algorithm does the maximum possible number of operations.
worst case
A best case or worst case scenario describes contents of the algorithm’s input data only. The input data size must remain a blank. Otherwise, the overwhelming majority of algorithms would have a best case of N=0, since no input data would be processed. In both theory and practice, saying “the best case is when the algorithm doesn’t process any data” is not useful. Complexity analysis always treats the input data size as a variable.
variable, N
An algorithm’s blank is a function, S(N), that represents the number of fixed-size memory units used by the algorithm for an input of size N.
space complexity
The space complexity of an algorithm that duplicates a list of numbers is blank where k is a constant representing memory used for things like the loop counter and list pointers.
S(N) = 2N + k,
Space complexity includes the blank and blank allocated by the algorithm.
input data and additional memory
An algorithm’s blank is the space complexity not including the input data
auxiliary space complexity
An algorithm to find the maximum number in a list will have a space complexity of S(N) = N + k, but an auxiliary space complexity of blank, where k is a constant.
S(N) = k
A blank is an algorithm that breaks the problem into smaller subproblems and applies the algorithm itself to solve the smaller subproblems.
recursive algorithm