Analysis of Algorithms, I
CSOR W4231
Computer Science Department
Copyright By PowCoder代写 加微信 powcoder
Columbia University
Quicksort, randomized quicksort, occupancy problems
1 Quicksort
2 Randomized Quicksort
3 Random variables and linearity of expectation
4 Analysis of randomized Quicksort
5 Occupancy problems
1 Quicksort
2 Randomized Quicksort
3 Random variables and linearity of expectation
4 Analysis of randomized Quicksort
5 Occupancy problems
Quicksort facts
Quicksort is a divide and conquer algorithm
It is the standard algorithm used for sorting
It is an in-place algorithm
Its worst-case running time is Θ(n2) but its average-case running time is Θ(n log n)
We will use it to introduce randomized algorithms
Quicksort: main idea
Pick an input item, call it pivot, and place it in its final location in the sorted array by re-organizing the array so that:
all items ≤ pivot are placed before pivot
all items > pivot are placed after pivot
Recursively sort the subarray to the left of pivot. Recursively sort the subarray to the right of pivot.
Quicksort pseudocode
Quicksort(A, lef t, right)
if |A| = 0 then return //A is empty end if
split = Partition(A, lef t, right) Quicksort(A, lef t, split − 1)
Quicksort(A, split + 1, right)
Initial call: Quicksort(A, 1, n)
Subroutine Partition(A,left,right)
Notation: A[i,j] denotes the portion of A starting at position i and ending at position j.
Partition(A, lef t, right)
1. picks a pivot item
2. re-organizes A[left,right] so that
all items before pivot are ≤ pivot
all items after pivot are > pivot
3. returns split, the index of pivot in the re-organized array
After Partition, A[left,right] looks as follows:
≤pivot >pivot
left split right
Implementing Partition
1. Pick a pivot item: for simplicity, always pick the last item of the array as pivot, i.e., pivot = A[right].
Thus A[right] will be placed in its final location in the sorted output when Partition returns; it will never be used (or moved) again until the algorithm terminates.
2. Re-organize the input array A in place. How?
(What if we didn’t care to implement Partition in place?)
Implementing Partition in place
Partition examines the items in A[left,right] one by one and maintains three regions in A. Specifically, after examining the j-th item for j ∈ [left, right − 1], the regions are:
1. Left region: starts at left and ends at split; A[left,split] contains all items ≤ pivot examined so far.
2. Middle region: starts at split + 1 and ends at j;
A[split + 1, j] contains all items > pivot examined so far.
3. Right region: starts at j + 1 and ends at right − 1; A[j + 1, right − 1] contains all unexamined items.
≤pivot >pivot unexamined
split split+1 j j+1 right-1 right
End of j-th iteration
Implementing Partition in place (cont’d)
At the beginning of iteration j, A[j] is compared with pivot. If A[j] ≤ pivot
1. swap A[j] with A[split + 1], the first element of the middle region (items > pivot): since A[split + 1] > pivot, it is “safe” to move it to the end of the middle region
2. increment split to include A[j] in the left region (items > pivot)
Iteration j: when A[j] ≤ pivot
Beginning of iteration j (assume A[j]≤pivot)
≤pivot >pivot
split split+1
unexamined
End of iteration j: A[j] got swapped with A[split+1], split got updated to split+1
>pivot unexamined
Example: A = {1, 3, 7, 2, 6, 4, 5}, Partition(A, 1, 7)
unexamined
unexamined
unexamined
>pivot unexamined
1 39 7 2 6 4 5
>pivot 1 3 j
1 39 split j
beginning of iteration j=1 A[j]=1
beginning of iteration j=2 A[j]=3
beginning of iteration j=3 A[j]=7
unexamined
beginning of iteration j=4, A[j]=2
beginning of iteration j=5 A[j]=6
1 39 2 7 6 4 5
1 39 2 7 6 4 5 split j
beginning of iteration j=6 A[j]=4
end of iteration j=6 A[j]=4
end of Partition
1 39 2 4 6 7 5 split j
5 7 6 split
Pseudocode for Partition
Partition(A, lef t, right)
pivot = A[right]
split = left − 1
for j=lefttoright−1 do
if A[j] ≤ pivot then swap(A[j], A[split + 1]) split = split + 1
end if end for
swap(pivot, A[split + 1]) //place pivot after A[split] (why?) return split + 1 //the final position of pivot
Analysis of Partition: correctness
Notation: A[i,j] denotes the portion of A that starts at position i and ends at position j.
For left ≤ j ≤ right − 1, at the end of loop j, 1. all items in A[left,split] are ≤ pivot; and 2. all items in A[split + 1, j] are > pivot
Remark: If the claim is true, correctness of Partition follows (why?).
Proof of Claim 1
By induction on j.
1. Base case: For j = left (that is, during the first execution of the for loop), there are two possibilities:
if A[left] ≤ pivot, then A[left] is swapped with itself and split is incremented to equal left;
otherwise, nothing happens.
In both cases, the claim holds for j = left.
2. Hypothesis: Assume that the claim is true for some left ≤ j < right − 1.
That is, at the end of loop j, all items in A[left,split] are ≤ pivot and all items in A[split + 1, j] are > pivot.
Proof of Claim 1 (cont’d)
3. Step: We will show the claim for j + 1. That is, we will show that after loop j + 1, all items in A[lef t, split] are ≤ pivot and all items in A[split + 1, j + 1] are > pivot.
At the beginning of loop j + 1, by the hypothesis, items in A[left, split] are ≤ pivot and items in A[split + 1, j] are > pivot.
Inside loop j + 1, there are two possibilities:
1. A[j + 1] ≤ pivot: then A[j + 1] is swapped with A[split + 1]. At this point, items in A[lef t, split + 1] are ≤ pivot and items in A[split + 2, j + 1] are > pivot. Incrementing split (the next step in the pseudocode) yields that the claim holds for j + 1.
2. A[j + 1] > pivot: nothing is done. The truth of the claim follows from the hypothesis.
This completes the proof of the inductive step.
Analysis of Partition: running time and space
Running time: on input size n, Partition goes through each of the n − 1 leftmost elements once and performs constant amount of work per element.
⇒ Partition requires Θ(n) time. Space: in-place algorithm
Analysis of Quicksort: correctness
Quicksort is a recursive algorithm; we will prove correctness by induction on the input size n.
We will use strong induction: the induction step at n requires that the inductive hypothesis holds at all steps 1,2,…,n−1 and not just at step n−1, as with simple induction.
Strong induction is most useful when several instances of the hypothesis are required to show the inductive step.
Analysis of Quicksort: correctness
Base case: for n = 0, Quicksort sorts correctly.
Hypothesis: for all 0 ≤ m < n, Quicksort correctly
sorts on input size m.
Step: show that Quicksort correctly sorts on input size n.
Partition(A, 1, n) re-organizes A so that all items
in A[1,...,split − 1] are ≤ A[split];
in A[split + 1,...,n] are > A[split].
Next, Quicksort(A, 1, split − 1), Quicksort(A, split + 1, n) will correctly sort their inputs (by the hypothesis). Hence
A[1] ≤ . . . ≤ A[split − 1] and A[split + 1] ≤ . . . ≤ A[n]. At this point, Quicksort terminates and A is sorted.
Analysis of Quicksort: space and running time
Space: in-place algorithm
Running time T(n): depends on the arrangement of the input elements
the sizes of the inputs to the two recursive calls –hence the form of the recurrence– depend on how pivot compares to the rest of the input items
Running time of Quicksort:
Suppose that in every call to Partition the pivot item is the median of the input.
Then every Partition splits its input into two lists of almost equal sizes, thus
T (n) = 2T (n/2) + Θ(n) = O(n log n). This is a “balanced” partitioning.
Exampleofbestcase: A=[1 3 2 5 7 6 4] Remark 1.
You can show that T (n) = O(n log n) for any splitting where the two subarrays have sizes αn, (1 − α)n respectively, for constant 0 < α < 1.
Running time of Quicksort: Worst Case
Upper bound for worst-case running time: T(n) = O(n2)
at most n calls to Partition (one for each item as pivot)
Partition requires O(n) time
This worst-case upper bound is tight:
If every time Partition is called pivot is greater (or smaller) than every other item, then its input is split into two lists, one of which has size 0.
This partitioning is very “unbalanced”: let c, d > 0 be constants, where T (0) = d; then
T(n) = T(n−1)+T(0)+cn = Θ(n2). △ A worst-case input is the sorted input!
Running time: average case analysis
Average case: what is an “average” input to sorting?
Depends on the application.
Inntuition why average-case analysis for uniformly distributed inputs to Quicksort is O(n log n) appears in your textbook.
We will use randomness within the algorithm to provide Quicksort with a uniform at random input.
1 Quicksort
2 Randomized Quicksort
3 Random variables and linearity of expectation
4 Analysis of randomized Quicksort
5 Occupancy problems
Two views of randomness in computation
1. Deterministic algorithm, randomness over the inputs
On the same input, the algorithm always produces the same output using the same time.
So far, we have only encountered such algorithms. The input is randomly generated according to some
underlying distribution.
Average case analysis: analysis of the running time of the algorithm on an average input.
Two views of randomness in computation (cont’d)
2. Randomized algorithm, worst-case (deterministic) input
On the same input, the algorithm produces the same output but different executions may require different running times.
The latter depend on the random choices of the algorithm (e.g., coin flips, random numbers).
Random samples are assumed independent of each other.
Worst-case input
Expected running time analysis: analysis of the running time of the randomized algorithm on a worst-case input.
Remarks on randomness in computation
1. Deterministic algorithms are a special case of randomized algorithms.
2. Even when equally efficient deterministic algorithms exist, randomized algorithms may be simpler, require less memory of the past or be useful for symmetry-breaking.
Randomized Quicksort
Can we use randomization so that Quicksort works with an “average” input even when it receives a worst-case input?
1. Explicitly permute the input.
2. Use random sampling to choose pivot: instead of using
A[right] as pivot, select pivot randomly.
Idea 1 (intuition behind random sampling).
No matter how the input is organized, we won’t often pick the largest or smallest item as pivot (unless we are really, really unlucky). Thus most often the partitioning will be “balanced”.
Pseudocode for randomized Quicksort
Randomized-Quicksort(A, lef t, right)
if |A| == 0 then return //A is empty
split = Randomized-Partition(A, lef t, right) Randomized-Quicksort(A, lef t, split − 1) Randomized-Quicksort(A, split + 1, right)
Randomized-Partition(A, lef t, right) b = random(lef t, right)
swap(A[b], A[right])
return Partition(A,left,right)
Subroutine random(i,j) returns a random number between i and j inclusive.
1 Quicksort
2 Randomized Quicksort
3 Random variables and linearity of expectation
4 Analysis of randomized Quicksort
5 Occupancy problems
Discrete random variables
To analyze the expected running time of a randomized algorithm we keep track of certain parameters and their expected size over the random choices of the algorithm.
To this end, we use random variables.
A discrete random variable X takes on a finite number of values, each with some probability. We’re interested in its expectation
E[X] = j · Pr[X = j]. j
Example 1: Bernoulli trial
Experiment 1: flip a biased coin which comes up heads with probability p
tailswithprobability1−p
Question: what is the expected number of heads?
Example 1: Bernoulli trial
Experiment 1: flip a biased coin which comes up heads with probability p
tailswithprobability1−p
Question: what is the expected number of heads? Let X be a random variable such that
1 , if coin flip comes heads X= 0 ,ifcoinflipcomestails
Example 1: Bernoulli trial
Experiment 1: flip a biased coin which comes up heads with probability p
tailswithprobability1−p
Question: what is the expected number of heads? Let X be a random variable such that
1 , if coin flip comes heads X= 0 ,ifcoinflipcomestails
Pr[X =1]=p
Pr[X =0]=1−p
E[X]=1·Pr[X =1]+0·Pr[X =0]=p
Indicator random variables
Indicator random variable: a discrete random variable that only takes on values 0 and 1.
Indicator random variables are used to denote occurrence (or not) of an event.
Example: in the biased coin flip example, X is an indicator random variable that denotes the occurrence of heads.
If X is an indicator random variable, then E[X] = Pr[X = 1].
Example 2: Bernoulli trials
Experiment 2: flip the biased coin n times Question: what is the expected number of heads?
Example 2: Bernoulli trials
Experiment 2: flip the biased coin n times Question: what is the expected number of heads?
Answer 1: Let X be the random variable counting the number of times heads appears.
Pr[X = j]?
E[X] = j · Pr[X = j]. j=0
Example 2: Bernoulli trials
Experiment 2: flip the biased coin n times Question: what is the expected number of heads?
Answer 1: Let X be the random variable counting the number of times heads appears.
E[X] = j · Pr[X = j]. j=0
Pr[X = j]?
X follows the binomial distribution B(n, p), thus
n j n−j Pr[X=j]= j p(1−p)
Example 2: Bernoulli trials
A different way to think about X:
Answer 2: for 1 ≤ i ≤ n, let Xi be an indicator random
variable such that
1 , if i-th coin flip comes heads Xi = 0 , if i-th coin flip comes tails
Example 2: Bernoulli trials
A different way to think about X:
Answer 2: for 1 ≤ i ≤ n, let Xi be an indicator random
variable such that
1 , if i-th coin flip comes heads
Xi = 0 , if i-th coin flip comes tails Define the random variable
We want E[X]. By Fact 1, E[Xi] = p, for all i.
Linearity of expectation
X = Xi, E[Xi] = p, E[X] =?
Linearity of expectation
X = Xi, E[Xi] = p, E[X] =?
Remark 1: X is a complicated random variable defined as the sum of simpler random variables whose expectation is known.
Linearity of expectation
X = Xi, E[Xi] = p, E[X] =?
Remark 1: X is a complicated random variable defined as the
sum of simpler random variables whose expectation is known.
Proposition 1 (Linearity of expectation).
Let X1, . . . , Xk be arbitrary random variables. Then
E[X1 +X2 +…+Xk]=E[X1]+E[X2]+…+E[Xk]
Linearity of expectation
X = Xi, E[Xi] = p, E[X] =?
Remark 1: X is a complicated random variable defined as the
sum of simpler random variables whose expectation is known.
Proposition 1 (Linearity of expectation).
Let X1, . . . , Xk be arbitrary random variables. Then
E[X1 +X2 +…+Xk]=E[X1]+E[X2]+…+E[Xk]
Remark 2: We made no assumptions on the random variables. For example, they do not need be independent.
Back to example 2: Bernoulli trials
Answer 2: for 1 ≤ i ≤ n, let Xi be an indicator random variable such that
1 , if i-th coin flip comes heads Xi = 0 , if i-th coin flip comes tails
Define the random variable
By Fact 1, E[Xi] = p, for all i. By linearity of expectation, nnn
E[X] = EX = E[X ] = p = np. ii
i=1 i=1 i=1
1 Quicksort
2 Randomized Quicksort
3 Random variables and linearity of expectation
4 Analysis of randomized Quicksort
5 Occupancy problems
Expected running time of randomized Quicksort
Let T(n) be the expected running time of Randomized-Quicksort.
We want to bound T(n).
Randomized-Quicksort differs from Quicksort only in
how they select their pivot elements.
⇒ We will analyze Randomized-Quicksort based on Quicksort and Partition.
Pseudocode for Partition
Partition(A, lef t, right)
pivot = A[right]
split = left − 1
for j=lefttoright−1 do
if A[j] ≤ pivot then swap(A[j], A[split + 1]) split = split + 1
end if end for
swap(pivot, A[split + 1]) return split + 1
line 1 line 2 line3 line 4 line 5 line 6
line 7 line 8
Few observations
1. How many times is Partition called?
Few observations
1. How many times is Partition called? At most n.
2. Further, each Partition call spends some work 1. outside the for loop
2. inside the for loop
Few observations
1. How many times is Partition called? At most n.
2. Further, each Partition call spends some work 1. outside the for loop
every Partition spends constant work outside the for loop
at most n calls to Partition
⇒ total work outside the for loop in all calls to Partition is O(n)
2. inside the for loop
Few observations
1. How many times is Partition called? At most n.
2. Further, each Partition call spends some work 1. outside the for loop
every Partition spends constant work outside the for loop
at most n calls to Partition
⇒ total work outside the for loop in all calls to Partition is O(n)
2. inside the for loop
let X be the total number of comparisons performed at line 4 in
all calls to Partition
each comparison may require some further constant work (lines 5
⇒ total work inside the for loop in all calls to Partition is O(X)
Towards a bound for T(n)
X = the total number of comparisons in all Partition calls. The running time of Randomized-Quicksort is
Since X is a random variable, we need E[X] to bound T(n).
Towards a bound for T(n)
X = the total number of comparisons in all Partition calls. The running time of Randomized-Quicksort is
Since X is a random variable, we need E[X] to bound T(n).
Fix any two input items. During the execution of the algorithm, they may be compared at most once.
Towards a bound for T(n)
X = the total number of comparisons in all Partition calls. The running time of Randomized-Quicksort is
Since X is a random variable, we need E[X] to bound T(n).
Fix any two input items. During the execution of the algorithm, they may be compared at most once.
Comparisons are only performed with the pivot of each Partition call. After Partiton returns, pivot is in its final location in the output and will not be part of the input to any future recursive call.
Simplifying the analysis
There are n numbers in the input, hence n = n(n−1) 22
distinct (unordered) pairs of input numbers.
From Fact 1, the algorithm will perform at most n 2
comparisons.
What is the expected number of comparisons?
Simplifying the analysis
There are n numbers in the input, hence n = n(n−1) 22
distinct (unordered) pairs of input numbers.
From Fact 1, the algorithm will perform at most n
comparisons.
What is the expected number of comparisons? To simplify the analysis
relabel the input as z1,z2,…,zn, where zi is the i-th smallest number.
assume that all input numbers are distinct; thus zi < zj, for i < j.
Writing X as the sum of indicator random variables
Let Xij be an indicator random variable such that
1, if zi and zj are ever compared Xij = 0, otherwise
Writing X as the sum of indicator random variables
Let Xij be an indicator random variable such that 1, if zi and zj are ever compared
The total number of comparisons is given by X = Xij. 1≤i