CS140-lecture-20211006

Common divide and conquer problems #

Counting Inversions #

image_2021-10-06-08-58-25

Inversions are the number of out of order pairs in an array of numbers. We can use the amount of inversions as a ranking for multiple arrays.

image_2021-10-06-09-00-51

If we consider the first array as sorted (the indices), we can use the second array’s indices as a rank to compare.

When we try and count inversions, we are given an array of \( n \) numbers.

image_2021-10-06-09-02-02

We can use divide and conquer to count the number of inversions.

  • split the array into 2 subarrays
  • count the inversions in each subarray
  • combine the answer

image_2021-10-06-09-03-53

The problem with the combination step is that we have to count the number of inversions between the 2 subarrays now. So after each subarray is counted, we can loop over the first array and compare to each element of the second array. We can’t really do better than this. This means the combination step is \( \Theta(n^2) \) .

\[\begin{aligned} T(n) &= 2T \left( \frac{n}{2} \right) + \Theta(n^2) \\ &= \Theta(n^2) \end{aligned}\]

This is no different than just looping over the entire original array and comparing the numbers.

So how can we do better? If we are never working with sorted arrays, we cannot do better. However, if we sort the array before we return the subarray result, we can do better.

image_2021-10-06-09-13-36

While we are mering the 2 subarrays, we can count the inversions. If the smaller value is coming from the second subarray, then we have an inversion. If we have \( m \) items in a subarray, and \( i \) points to the item in the first subarray, then we have \( m-i+1 \) inversions for the item in the second subarray.

image_2021-10-06-09-27-48 image_2021-10-06-09-28-19

Closest pair of points #

image_2021-10-06-09-29-28

If we are working with a 1D array, we can sort them and then loop thru once and find the adjacent pairs.

image_2021-10-06-09-31-36

We can divide both the \( x \) and \( y \) axis in half:

image_2021-10-06-09-33-05

Note: Usually if we divide our problem into subproblems of the same size, we get better asymptotic complexity.

image_2021-10-06-09-35-12

So how would we combine the result? Its not easy to do better than \( \Theta(n^2) \) time. But, we want to do better.

What if instead we just divide into 2 parts?

image_2021-10-06-09-37-30

The problem is since we are comparing each point to each other point, we still end up with \( \Theta(n^2) \) . We eliminate points that are bigger than the 2 subarray returns. We can take the min of the 2 subarray returns, and create a boundary on the left and right of the division and check those points only.

image_2021-10-06-09-41-05

However, the problem is we don’t know whether or not all points will fall in the center band.

image_2021-10-06-09-41-54

We can also enforce the restriction in the \( y \) direction. So if we sort the numbers on the \( y \) coordinates, and the index is greater than or equal to the min number, then they will be at least that far away.

image_2021-10-06-09-42-53

If 2 points fall inside one grid square, then the distance between them will be less than the min of the subarrays.

image_2021-10-06-09-44-45 image_2021-10-06-09-45-25

So we loop for each item 12 times, so we get a complexity of \( \Theta(n) \) for combine.

image_2021-10-06-09-48-26

So, this results in a \( \Theta(n \lg n) \) runtime complexity. However, this is no better than just sorting by the coordinates in the beginning. So how can we do better?

We can put the compute step outside of the recursion. We can also do the \( y \) coordinate sorting inside the recursion.

image_2021-10-06-09-52-18

Solving recurrences #

image_2021-10-06-11-04-13 image_2021-10-06-13-12-58

So how can we go from the recurrences to the solutions?

Binary search recurrences #

image_2021-10-06-13-13-59 image_2021-10-06-13-15-13 image_2021-10-06-13-15-17 image_2021-10-06-13-15-25

If lo > hi or if we find the value we’re looking for, the complexity is \( \Theta(1) \) . On the recursive call, we have a complexity of \[\begin{aligned} T(n) &= T \left( \frac{n}{2} \right) + \Theta(1) + \Theta(1) + \Theta(1) \\ &= T \left( \frac{n}{2} \right) + c \\ &= O(\lg n) \end{aligned}\]

Methods for solving recurrences #

image_2021-10-06-13-22-04

Iteration method #

image_2021-10-06-13-22-20 image_2021-10-06-13-25-13

Here \( k = \lg n \) . So overall we get \[\begin{aligned} &= c \lg n + \Theta(1) \\ &= \Theta( \lg n) \end{aligned}\]

What if \( n \) is not a power of 2? Asymptotically it will still be a linear complexity.

image_2021-10-06-13-31-59

So since we complete \( n \) steps \( k \) times, plus \( 2^k \) constant times. Since \( k = \lg n \) the entire thing equals \[\begin{aligned} &= n \lg n + n \\ &= \Theta(n \lg n) \end{aligned}\]

Substitution method #

  1. Guess a solution
  2. Use induction to prove that the solution works

image_2021-10-06-13-34-18 image_2021-10-11-12-05-50

\[\begin{aligned} T(n) & = T \left( \frac{n}{2} \right) + c \leq d \lg \left( \frac{n}{2} \right) + c \\ & = d \lg n - d + c \leq d \lg n \end{aligned}\]

If \( -d + c \leq 0, d \geq c \) .

image_2021-10-11-12-11-43

\[\begin{aligned} T(n) & = T(n-1) + n \leq c(n-1)^2 + n \\ & = cn^2 - (2cn - c - n) \leq cn^2 \end{aligned}\]

If \( 2cn - c - n \geq 0 \)

image_2021-10-11-12-20-45 image_2021-10-11-12-21-12 image_2021-10-11-13-07-19 image_2021-10-11-13-10-13 image_2021-10-11-13-29-01

Changing variables #

image_2021-10-11-13-32-09

Worse case analysis of quicksort #

image_2021-10-11-13-33-35 image_2021-10-11-13-37-24