Searching and Sorting Algorithms - Chapter 11 Flashcards

1
Q

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.

A

Linear search

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

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.

A

runtime

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

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

A

32

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

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.

A

binary search,

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

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).

A

Binary search

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

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

A

floor(log2 N) + 1

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

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.

A

floor division

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

A blank is an operation that, for a given processor, always operates in the same amount of time, regardless of input values.

A

constant time operation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

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.

A

constant time operations

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

The blank being used, as well as the blank running the code, both affect what is and what is not a constant time operation.

A

programming language
hardware

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Common constant time operations

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

An algorithm with runtime complexity T(N) has a blank and blank.

A

lower bound and an upper bound

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Blank A function f(N) that is ≤ the best case T(N), for all values of N ≥ 1.

A

Lower bound:

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Blank: A function f(N) that is ≥ the worst case T(N), for all values of N ≥ 1.

A

Upper bound

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

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.

A

infinite number

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Two additional criteria are commonly used to choose a preferred upper or lower bound. The preferred bound:

A

is a single-term polynomial and
bounds T(N) as tightly as possible.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Blank is the classification of runtime complexity that uses functions that indicate only the growth rate of a bounding function.

A

Asymptotic notation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Three asymptotic notations are commonly used in complexity analysis:

A

O notation
Ω notation
Θ notation provides a growth rate that is both an upper and lower bound.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Blank provides a growth rate for an algorithm’s upper bound.

A

O notation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Blank provides a growth rate for an algorithm’s lower bound.

A

Ω notation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Blank provides a growth rate that is both an upper and lower bound.

A

Θ notation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Blank is a mathematical way of describing how a function (running time, or runtime, of an algorithm) behaves in relation to the input size.

A

Big O notation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

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.

A

equivalent

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Given a function that describes the runtime of an algorithm, the Big O notation for that function can be determined using the following rules

A

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.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

c · O(f(x)) Big O notation

A

O(f(x))

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

c + O(f(x)) Big O notation

A

O(f(x))

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

g(x) · O(f(x)) Big O notation

A

O(g(x)·O(f(x)))

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

g(x) + O(f(x)) Big O notation

A

O(g(x) + O(f(x)))

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

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.

A

large input sizes

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

O(1) Name

A

Constant

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

O-type
def find_min(x, y):
if x < y:
return x
else:
return y

A

O(1) Constant

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

O(log N) Name

A

Logarithmic

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

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

A

O(log N or Logarithmic

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

O(N) name

A

Linear

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

O type -
def linear_search(numbers, key):
for i in range(len(numbers)):
if numbers[i] == key:
return i
return -1 # not found

A

O(N) or Linear

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

O(N log N) name

A

Log-linear

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

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

A

O(N log N) or Log-linear

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q

O(N^2) name

A

Quadratic

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

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
A

O(N^2) or Quadratic

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

O(c^n) Name

A

Exponential

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

O type -
def fibonacci(N):
if (1 == N) or (2 == N):
return N
return fibonacci(N-1) + fibonacci(N-2)

A

O(c^n) or Exponential

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

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.

A

big-O notation

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
43
Q

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.

A

worst-case runtime

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
44
Q

Since constants are omitted in big-O notation, any constant number of constant time operations is blank.

A

O(1)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
45
Q

Runtime analysis for blank requires summing the runtime of the inner loop over each outer loop iteration.

A

nested loops

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
46
Q

Blank is typically measured by the algorithm’s computational complexity.

A

Algorithm efficiency

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
47
Q

Blank is the amount of resources used by the algorithm.

A

Computational complexity

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
48
Q

The most common resources considered for computational complexity are the blank and blank.

A

runtime and memory usage

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
49
Q

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.

A

runtime complexity

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
50
Q

An algorithm’s blank is the scenario where the algorithm does the minimum possible number of operations.

A

best case

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
51
Q

An algorithm’s blank is the scenario where the algorithm does the maximum possible number of operations.

A

worst case

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
52
Q

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.

A

variable, N

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
53
Q

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.

A

space complexity

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
54
Q

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.

A

S(N) = 2N + k,

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
55
Q

Space complexity includes the blank and blank allocated by the algorithm.

A

input data and additional memory

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
56
Q

An algorithm’s blank is the space complexity not including the input data

A

auxiliary space complexity

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
57
Q

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.

A

S(N) = k

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
58
Q

A blank is an algorithm that breaks the problem into smaller subproblems and applies the algorithm itself to solve the smaller subproblems.

A

recursive algorithm

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
59
Q

Because a problem cannot be endlessly divided into smaller subproblems, a recursive algorithm must have a blank: A case where a recursive algorithm completes without applying itself to a smaller subproblem.

A

base case

60
Q

A blank is a function that calls itself. Recursive functions are commonly used to implement recursive algorithms.

A

recursive function

61
Q

Factorial, CumulativeSum, and ReverseList

A

Sample recursive functions

62
Q

The blank is a numerical sequence where each term is the sum of the previous 2 terms in the sequence, except the first 2 terms, which are 0 and 1.

A

Fibonacci sequence

63
Q

A recursive function can be used to calculate a blank: A term in the Fibonacci sequence.

A

Fibonacci number

64
Q

FibonacciNumber(termIndex) {
if (termIndex == 0)
return 0
else if (termIndex == 1)
return 1
else
return FibonacciNumber(termIndex - 1) + FibonacciNumber(termIndex - 2)
}

A

FibonacciNumber recursive function

65
Q

Blank is an algorithm that searches a sorted list for a key by first comparing the key to the middle element in the list and recursively searching half of the remaining list so long as the key is not found.

A

Binary search

66
Q

The runtime complexity T(N) of a blank will have function T on both sides of the equation. Ex: Binary search performs constant time operations, then a recursive call that operates on half of the input, making the runtime complexity T(N) = O(1) + T(N / 2)

A

recursive function

67
Q

blank: A function f(N) that is defined in terms of the same function operating on a value < N.

A

recurrence relation

68
Q

Using O-notation to express runtime complexity of a recursive function requires blank. For simpler recursive functions such as binary search, runtime complexity can be determined by expressing the number of function calls as a function of N.

A

solving the recurrence relation

69
Q

The runtime complexity of any recursive function can be split into 2 parts: blank and blank. Ex: For binary search’s T(N) = O(1) + T(N / 2), O(1) represents operations directly done by the function and T(N / 2) represents operation done by a recursive call.

A

operations done directly by the function and operations done by recursive calls made by the function

70
Q

A useful tool for solving recurrences is a blank: A visual diagram of an operation done by a recursive function, that separates operations done directly by the function and operations done by recursive calls.

A

recursion tree

71
Q

A blank is a sorting algorithm that has an average runtime complexity of O(NlogN) or better

A

fast sorting algorithm

72
Q

Average case runtime complexity of Selection sort

A

O(N^2)

73
Q

Average case runtime complexity of Insertion sort

A

O(N^2)

74
Q

Average case runtime complexity of Shell sort

A

O(N^1.5)

75
Q

Average case runtime complexity of Quicksort

A

O(NlogN)

76
Q

Average case runtime complexity of Merge sort

A

O(NlogN)

77
Q

Average case runtime complexity of Heap sort

A

O(NlogN)

78
Q

Average case runtime complexity of Radix sort

A

O(N)

79
Q

Name the three sorting algorithms that aren’t considered fast sorting algorithms

A

Selection sort, Insert sort, Shell sort

80
Q

Name the four fast sorting algorithms

A

Quicksort, Merge sort, Heap sort, Radix sort

81
Q

A blank is a sorting algorithm that operates on an array of elements that can be compared to each other. Ex: An array of strings can be sorted with a comparison sorting algorithm, since two strings can be compared to determine if the one string is less than, equal to, or greater than another string.

A

element comparison sorting algorithm

82
Q

Blank, blank, blank, blank, blank and blank are all comparison sorting algorithms. Blank, in contrast, subdivides each array element into integer digits and is not a comparison sorting algorithm.

A

Selection sort, insertion sort, shell sort, quicksort, merge sort, and heap sort
Radix sort

83
Q

A fast sorting algorithm’s best or worst case runtime complexity may differ from the blank.

A

average runtime complexity

84
Q

Quicksort - Best case runtime complexity, Average case runtime complexity, and Worst case runtime complexity

A

O(NlogN), O(NlogN), O(N^2)

85
Q

Merge sort - Best case runtime complexity, Average case runtime complexity, and Worst case runtime complexity

A

O(NlogN), O(NlogN), O(NlogN)

86
Q

Heap sort - Best case runtime complexity, Average case runtime complexity, and Worst case runtime complexity

A

O(N), O(NlogN), O(NlogN)

87
Q

Radix sort - Best case runtime complexity, Average case runtime complexity, and Worst case runtime complexity

A

O(N), O(N), O(N)

88
Q

Blank is the process of converting a list of elements into ascending (or descending) order.

A

Sorting

89
Q

Blank is a sorting algorithm that treats the input as two parts, sorted and unsorted, and repeatedly selects the proper next value to move from the unsorted part to the end of the sorted part.

A

Selection sort

90
Q

The index variable i denotes the blank. Elements to the left of i are sorted, and elements including and to the right of i are unsorted. All elements in the unsorted part are searched to find the index of the element with the smallest value.

A

dividing point

91
Q

Selection sort has the advantage of blank, involving one loop nested within another loop

A

being easy to code

92
Q

The selection sort algorithm runtime is blank

A

O(N^2).

93
Q

def blank(numbers):
for i in range(len(numbers)-1):

  # Find index of smallest remaining element
  index_smallest = i
  for j in range(i+1, len(numbers)):
     
     if numbers[j] < numbers[index_smallest]:
        index_smallest = j
  
  # Swap numbers[i] and numbers[index_smallest]
  temp = numbers[i]
  numbers[i] = numbers[index_smallest]
  numbers[index_smallest] = temp
A

selection_sort

94
Q

Blank is a sorting algorithm that treats the input as two parts, sorted and unsorted, and repeatedly inserts the next value from the unsorted part into the correct location in the sorted part.

A

Insertion sort

95
Q

The index variable i denotes the starting position of the current element in the unsorted part. Initially, the first element (i.e., element at index 0) is assumed to be sorted, so the outer for loop initializes i to blank. The inner while loop inserts the current element into the sorted part by repeatedly swapping the current element with the elements in the sorted part that are larger. Once a smaller or equal element is found in the sorted part, the current element has been inserted into the correct location and the while loop terminates.

A

1

96
Q

Insertion sort’s typical runtime is blank

A

O(N^2)

97
Q

For sorted or nearly sorted inputs, insertion sort’s runtime is blank

A

O(N)

98
Q

A blank contains only a few elements not in sorted order.

A

nearly sorted list

99
Q

Create a list of unsorted values

def blank(numbers):
for i in range(1, len(numbers)):
j = i

    # Insert numbers[i] into sorted part 
    # stopping once numbers[i] in correct position
    while j > 0 and numbers[j] < numbers[j - 1]:
        # Swap numbers[j] and numbers[j - 1]
        temp = numbers[j]
        numbers[j] = numbers[j - 1]
        numbers[j - 1] = temp
        j -= 1

numbers = [10, 2, 78, 4, 45, 32, 7, 11]

Print unsorted list
print(‘UNSORTED:’, numbers)

Call the insertion_sort function
insertion_sort(numbers)

Print sorted list
print(‘SORTED:’, numbers)

A

insertion_sort

100
Q

Blank is a sorting algorithm that treats the input as a collection of interleaved lists, and sorts each list individually with a variant of the insertion sort algorithm.

A

Shell sort

101
Q

Shell sort uses blank to determine the number of interleaved lists.

A

gap values

102
Q

A blank is a positive integer representing the distance between elements in an interleaved list. For each interleaved list, if an element is at index i, the next element is at index i + gap value.

A

gap value

103
Q

Shell sort begins by choosing a gap value K and sorting K interleaved lists in place. Shell sort finishes by performing a standard insertion sort on the entire array. Because the interleaved parts have already been sorted, smaller elements will be close to the array’s beginning and larger elements towards the end. Blank can then quickly sort the nearly-sorted array.

A

Insertion sort

104
Q

If a gap value of K is chosen, creating K entirely new lists would be blank. Instead of creating new lists, shell sort sorts interleaved lists in-place with a variation of the insertion sort algorithm. The insertion sort algorithm variant redefines the concept of “next” and “previous” items. For an item at index X, the next item is at X + K, instead of X + 1, and the previous item is at X - K instead of X - 1.

A

computationally expensive

105
Q

Shell sort begins by picking an arbitrary collection of gap values. For each gap value K, K calls are made to the insertion sort variant function to sort K interleaved lists. Shell sort ends with a final gap value of blank, to finish with the regular insertion sort.

A

1

106
Q

Shell sort tends to perform well when choosing gap values in blank. A common option is to choose powers of 2 minus 1, in descending order

A

descending order

107
Q

This gap selection technique results in shell sort’s time complexity being no worse than blank

A

O(N^3/2)

108
Q

def blank(numbers, start_index, gap):
for i in range(start_index + gap, len(numbers), gap):
j = i
while (j - gap >= start_index) and (numbers[j] < numbers[j - gap]):
temp = numbers[j]
numbers[j] = numbers[j - gap]
numbers[j - gap] = temp
j = j - gap

A

insertion_sort_interleaved

109
Q

Blank is a sorting algorithm that repeatedly partitions the input into low and high parts (each unsorted), and then recursively sorts each of those parts.

A

Quicksort

110
Q

To partition the input, quicksort chooses a blank to divide the data into low and high parts.

A

pivot

111
Q

The pivot can be any value within the array, commonly the value of the blank. Ex: For the list [4, 34, 10, 25, 1], the middle element is located at index 2 (the middle of indices 0..4) and has a value of 10.

A

middle array element

112
Q

Once partitioned, each partition needs to be sorted. Quicksort is typically implemented as a blank using calls to quicksort the low and high partitions. This recursive sorting process continues until a partition has one or zero elements, and thus is already sorted.

A

recursive algorithm

113
Q

The quicksort algorithm’s runtime is typically blank.

A

O(N log N)

114
Q

Quicksort has several blank, the first level dividing the input into 2 parts, the second into 4 parts, the third into 8 parts, etc. At each level, the algorithm does at most N comparisons moving the l and h indices. If the pivot yields two equal-sized parts, then there will be log N levels, requiring the N * log N comparisons

A

partitioning levels

115
Q

For typical unsorted data, such equal partitioning occurs. However, partitioning may yield unequal-sized parts in some cases. If the pivot selected for partitioning is the smallest or largest element, one partition will have just one element, and the other partition will have all other elements. If this unequal partitioning happens at every level, there will be N - 1 levels, yielding (N-1)(N)
, which is blank

A

O(N^2)

116
Q

def blank(numbers, start_index, end_index):
# Select the middle value as the pivot.
midpoint = start_index + (end_index - start_index) // 2
pivot = numbers[midpoint]

# "low" and "high" start at the ends of the list segment
# and move towards each other.
low = start_index
high = end_index
   
done = False
while not done:
    # Increment low while numbers[low] < pivot
    while numbers[low] < pivot:
        low = low + 1
  
    # Decrement high while pivot < numbers[high]
    while pivot < numbers[high]:
        high = high - 1
  
    # If low and high have crossed each other, the loop
    # is done. If not, the elements are swapped, low is
    # incremented and high is decremented.
    if low >= high:
        done = True
    else:
        temp = numbers[low]
        numbers[low] = numbers[high]
        numbers[high] = temp
        low = low + 1
        high = high - 1
   
# "high" is the last index in the left segment.
return high
A

partition

117
Q

def blank(numbers, start_index, end_index):
# Only attempt to sort the list segment if there are
# at least 2 elements
if end_index <= start_index:
return

# Partition the list segment
high = partition(numbers, start_index, end_index)

# Recursively sort the left segment
quicksort(numbers, start_index, high)

# Recursively sort the right segment
quicksort(numbers, high + 1, end_index)
A

quicksort

118
Q

Blank is a sorting algorithm that divides a list into two halves, recursively sorts each half, and then merges the sorted halves to produce a sorted list. The recursive partitioning continues until a list of one element is reached, as a list of one element is already sorted.

A

Merge sort

119
Q

The merge sort algorithm uses blank to keep track of the elements to sort for each recursive call. The index variable i is the index of the first element in the list, and the index variable k is the index of the last element. The index variable j is used to divide the list into two halves. Elements from i to j are in the left half, and elements from j + 1 to k are in the right half.

A

three index variables

120
Q

Merge sort merges the two sorted partitions into a single list by repeatedly selecting the blank from either the left or right partition and adding that element to a temporary merged list. Once fully merged, the elements in the temporary merged list are copied back to the original list.

A

smallest element

121
Q

The merge sort algorithm’s runtime is blank.

A

O(N log N)

122
Q

Merge sort requires blank additional memory elements for the temporary array of merged elements. For the final merge operation, the temporary list has the same number of elements as the input. Some sorting algorithms sort the list elements in place and require no additional memory but are more complex to write and understand.

A

O(N)

123
Q

def blank(numbers, i, j, k):
merged_size = k - i + 1 # Size of merged partition
merged_numbers = [0] * merged_size # Dynamically allocates temporary array
# for merged numbers
merge_pos = 0 # Position to insert merged number
left_pos = i # Initialize left partition position
right_pos = j + 1 # Initialize right partition position

# Add smallest element from left or right partition to merged numbers
while left_pos <= j and right_pos <= k:
    if numbers[left_pos] <= numbers[right_pos]:
        merged_numbers[merge_pos] = numbers[left_pos]
        left_pos += 1
    else:
        merged_numbers[merge_pos] = numbers[right_pos]
        right_pos += 1
    merge_pos = merge_pos + 1
   
# If left partition is not empty, add remaining elements to merged numbers
while left_pos <= j:
    merged_numbers[merge_pos] = numbers[left_pos]
    left_pos += 1
    merge_pos += 1
   
# If right partition is not empty, add remaining elements to merged numbers
while right_pos <= k:
    merged_numbers[merge_pos] = numbers[right_pos]
    right_pos = right_pos + 1
    merge_pos = merge_pos + 1
   
# Copy merge number back to numbers
for merge_pos in range(merged_size):
    numbers[i + merge_pos] = merged_numbers[merge_pos]

def merge_sort(numbers, i, k):
j = 0

if i < k:
    j = (i + k) // 2  # Find the midpoint in the partition

    # Recursively sort left and right partitions
    merge_sort(numbers, i, j)
    merge_sort(numbers, j + 1, k)
        
    # Merge left and right partition in sorted order
    merge(numbers, i, j, k)

Create a list of unsorted values
numbers = [61, 76, 19, 4, 94, 32, 27, 83, 58]

Print unsorted list
print(‘UNSORTED:’, numbers)

Initial call to merge_sort
merge_sort(numbers, 0, len(numbers) - 1)

Print sorted list
print(‘SORTED:’, numbers)

A

merge

124
Q

Blank is a sorting algorithm designed specifically for integers. The algorithm makes use of a concept called buckets and is a type of bucket sort.

A

Radix sort

125
Q

Any array of integer values can be subdivided into buckets by using the integer values’ digits. A blank is a collection of integer values that all share a particular digit value. Ex: Values 57, 97, 77, and 17 all have a 7 as the 1’s digit, and would all be placed into bucket 7 when subdividing by the 1’s digit.

A

bucket

126
Q

Blank is a sorting algorithm specifically for an array of integers: The algorithm processes one digit at a time starting with the least significant digit and ending with the most significant. Two steps are needed for each digit. First, all array elements are placed into buckets based on the current digit’s value. Then, the array is rebuilt by removing all elements from buckets, in order from lowest bucket to highest.

A

Radix sort

127
Q

In the extension, before radix sort completes, the algorithm allocates two buckets, blank and blank. The algorithm iterates through the array in order, placing negative integers in the negative bucket and non-negative integers in the non-negative bucket. The algorithm then reverses the order of the negative bucket and concatenates the buckets to yield a sorted array.

A

one for negative integers and the other for non-negative integers

128
Q

Returns the maximum length, in number of digits, out of all list elements
def blank_get_max_length(numbers):
max_digits = 0
for num in numbers:
digit_count = radix_get_length(num)
if digit_count > max_digits:
max_digits = digit_count
return max_digits

Returns the length, in number of digits, of value
def radix_get_length(value):
if value == 0:
return 1

digits = 0
while value != 0:
    digits += 1
    value = int(value / 10)
return digits

def radix_sort(numbers):
buckets = []
for i in range(10):
buckets.append([])

# Find the max length, in number of digits
max_digits = radix_get_max_length(numbers)

pow_10 = 1
for digit_index in range(max_digits):
    for num in numbers:
        bucket_index = (abs(num) // pow_10) % 10
        buckets[bucket_index].append(num)

    numbers.clear()
    for bucket in buckets:
        numbers.extend(bucket)
        bucket.clear()
  
    pow_10 = pow_10 * 10

negatives = []
non_negatives = []
for num in numbers:
    if num < 0:
        negatives.append(num)
    else:
        non_negatives.append(num)
negatives.reverse()
numbers.clear()
numbers.extend(negatives + non_negatives)

Create a list of unsorted values
numbers = [47, 81, 13, 5, 38, 96, 51, 64]

Print unsorted list
print(‘UNSORTED:’, numbers)

Call radix_sort to sort the list
radix_sort(numbers)

Print sorted list
print(‘SORTED:’, numbers)

A

radix

129
Q

Python has a built-in blank function that takes one list argument, sorts the list’s elements in ascending order using the less than (<) operator, and returns a new list with the sorted elements.

A

sorted()

130
Q

Python lists also have a blank method to do an in-place sorting of list elements in ascending order, meaning the list is modified and another list is not returned.

A

sort()

131
Q

sorted() and sort() can both take an optional keyword argument, blank, that when assigned with True sorts a list in descending order.

A

reverse

132
Q

The sorted() function and sort() method can take an optional blank, which is a function that determines how to sort the list. One common use of the key argument is to sort a list of strings without regard to case. Ex: The list [ “banana”, “Grape”, “Apple” ] by default sorts with uppercase letters coming before lowercase letters: [ “Apple”, “Grape”, “banana” ]. To sort as if all letters are lowercase, sorted() is called with argument key = str.lower. Note: The changed list item (“apple” instead of “Apple”) is only used temporarily during the sorting algorithm; the resulting list still has the original elements.

The argument is key = str.lower, not key = str.lower(), with parentheses. The key variable is assigned with the actual str.lower function itself, not by calling the str.lower() function.

A

key argument

133
Q

Another common use for the key argument is to sort a list by one of the blank if each element forms a tuple. Ex: List elements that contain both a student name and ID number: [(“Robert”, 135216), (“Amir”, 612901), (“Jennifer”, 194821)]. A key argument can be used to sort such a list by name or by ID number.

Custom key functions must be defined to have only one parameter, a single list element. The function uses that element variable to return whatever the sorting key should be. Note again that the key parameter is assigned with the custom key function’s name only, parentheses are not used.

A

elements’ values

134
Q

A special function, blank, defined in Python’s operator module, can be used to get a key from an element using an index instead of a custom key function. Ex: key = key_is_name can be replaced with key = operator.itemgetter(0), because the element names are found at index 0. itemgetter() takes an integer value argument and returns a function defined like key_is_name(element). Ex. operator.itemgetter(5) returns a function that takes a list element argument, and the function returns element[5].

A

itemgetter()

135
Q

Blank is a sorting algorithm that iterates through a list, comparing and swapping adjacent elements if the second element is less than the first element.

A

Bubble sort

136
Q

Bubble sort uses blank

A

nested loops

137
Q

Because of the nested loops, bubble sort has a runtime of blank

A

O(N^2)

138
Q

Blank is an algorithm that selects the kth smallest element in a list. Ex: Running quickselect on the list (15, 73, 5, 88, 9) with k = 0, returns the smallest element in the list, or 5.

A

Quickselect

139
Q

The best case and average runtime complexity of quickselect are both blank. In the worst case, quickselect may sort the entire list, resulting in a runtime of blank

A

O(N)
O(N^2)

140
Q

The quickselect() function has some similarities to the blank function: both functions are recursive, and both functions use the partition() function to rearrange a portion of the input list into sections that are less than or greater than a selected pivot. Unlike quicksort(), however, quickselect() is recursively applied to only one of the partitions.

A

quicksort()

141
Q

def blank(numbers, start_index, end_index, k):
if start_index >= end_index:
return numbers[start_index]

low_last_index = partition(numbers, start_index, end_index)
if k <= low_last_index:
    return quickselect(numbers, start_index, low_last_index, k)
  
return quickselect(numbers, low_last_index + 1, end_index, k)
A

quickselect

142
Q

Blank is a numerical sorting algorithm that distributes numbers into buckets, sorts each bucket with an additional sorting algorithm, and then concatenates buckets together to build the sorted result.

A

Bucket sort

143
Q

A blank is a container for numerical values in a specific range. Ex: All numbers in the range 0 to 49 may be stored in a bucket representing this range. Bucket sort is designed for arrays with non-negative numbers.

A

bucket

144
Q

Bucket sort first creates a list of buckets, each representing a range of blank. Collectively, the buckets represent the range from 0 to the maximum value in the array

A

numerical values

145
Q

The bucket index is calculated as
blank

A

floor(number*N/(M+1))