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

Lecture-3 (DivideAndConquer)

The document discusses sorting algorithms, particularly focusing on Insertion Sort and Merge Sort. It explains the mechanics of Insertion Sort, including its worst-case analysis and running time, and introduces Merge Sort as a more efficient divide-and-conquer approach with a running time of O(n log n). The document concludes by highlighting that Merge Sort is asymptotically faster than Insertion Sort and poses the question of whether better sorting algorithms exist.

Uploaded by

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

Lecture-3 (DivideAndConquer)

The document discusses sorting algorithms, particularly focusing on Insertion Sort and Merge Sort. It explains the mechanics of Insertion Sort, including its worst-case analysis and running time, and introduces Merge Sort as a more efficient divide-and-conquer approach with a running time of O(n log n). The document concludes by highlighting that Merge Sort is asymptotically faster than Insertion Sort and poses the question of whether better sorting algorithms exist.

Uploaded by

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

Divide And

Conquer
Merge Sort, Quick Sort
Sorting
• Arrange an unordered list of elements in some
order.
• Some common algorithms
• Bubble Sort
• Insertion Sort
• Merge Sort
• Quick Sort
Sorting
• Important primitive
• For today, we’ll pretend all elements are distinct.

6 4 3 8 1 5 2 7

1 2 3 4 5 6 7 8

Length of the list is n


Insertion Sort (Recap)
Insertion Sort 6 4 3 8 5
example

Insertion-Sort(A, n) Start by moving A[1] toward


for i = 1 to n – 1 the beginning of the list until
key = A[i]
j = i – 1 you find something smaller
while j >= 0 and A[j] > key (or can’t go any further):
A[j + 1] = A[j]
j = j – 1
A[j + 1] = key

6 4 3 8 5
4 6 3 8 5
Insertion Sort 6 4 3 8 5
example

Insertion-Sort(A, n)
for i = 1 to n – 1
Then move A[2]:
key = A[i] key = 3
j = i – 1
while j >= 0 and A[j] > key
A[j + 1] = A[j] 4 6 3 8 5
j = j – 1
A[j + 1] = key
4 6 6 8 5
4 4 6 8 5
3 4 6 8 5
Insertion Sort 6 4 3 8 5
example

Insertion-Sort(A, n)
for i = 1 to n – 1
Then move A[3]:
key = A[i] key = 8
j = i – 1
while j >= 0 and A[j] > key
A[j + 1] = A[j]
j = j – 1
A[j + 1] = key 3 4 6 8 5
3 4 6 8 5
Insertion Sort 6 4 3 8 5
example

Insertion-Sort(A, n)
for i = 1 to n – 1
Then move A[4]:
key = A[i] key = 5
j = i – 1
while j >= 0 and A[j] > key
A[j + 1] = A[j]
j = j – 1 3 4 6 8 5
A[j + 1] = key

3 4 6 8 8
3 4 6 6 8
3 4 5 6 8
Insertion Sort 6 4 3 8 5
example
Start by moving A[1] toward
the beginning of the list until
you find something smaller
(or can’t go any further): Then move A[3]:

6 4 3 8 5 3 4 6 8 5
4 6 3 8 5 3 4 6 8 5
Then move A[2]: Then move A[4]:
4 6 3 8 5 3 4 6 8 5
3 4 6 8 5 3 4 5 6 8
Then we are done!
Why does this work?

• Say you have a sorted list, 3 4 6 8 , and


another element 5 .

• Insert 5 right after the largest thing that’s still


smaller than 5 . (Aka, right after 4 ).

• Then you get a sorted list: 3 4 5 6 8


This sounds like a job for…

Proof By
Induction!
Outline of a proof by
induction
Let A be a list of length n
• Base case:
• A[:1] is sorted at the end of the 0’th iteration. ✓
• Inductive Hypothesis:
• A[:i+1] is sorted at the end of the ith iteration (of the outer loop).
• Inductive step:
• For any 0 < k < n, if the inductive hypothesis holds for i=k-1, then it holds for
i=k.
• Aka, if A[:k] is sorted at step k-1, then A[:k+1] is sorted at step k (previous
slide)
• Conclusion:
• The inductive hypothesis holds for i = 0, 1, …, n-1.
• In particular, it holds for i=n-1.
• At the end of the n-1’st iteration (aka, at the end of the algorithm), A[:n] = A is
sorted.
• That’s what we wanted! ✓
Worst-case Analysis
• In this class we will use worst-case analysis:
• We assume that a “bad guy” produces a worst-case
input for our algorithm, and we measure performance
on that worst-case input.

• How many operations are performed by the


insertion sort algorithm on the worst-case input?
How fast is InsertionSort?
• Let’s count the number of operations!
def InsertionSort(A):
for i in range(1,len(A)):
current = A[i]
j = i-1
while j >= 0 and A[j] > current:
A[j+1] = A[j]
j -= 1
A[j+1] = current

By my count*…
• variable assignments
• increments/decrements
• comparisons
• … *A complete count of the operation will be insignificant from
later discussion.
In this class we will
use…
• Big-Oh notation!
• Gives us a meaningful way to talk about the
running time of an algorithm, independent of
programming language, computing platform, etc.,
without having to count all the operations.
Main idea:
Focus on how the runtime scales with n (the input size).

(Heuristically: only pay attention to the


Some examples… largest function of n that appears.)

Asymptotic Running
Number of operations Time

We say this algorithm is


“asymptotically faster”
than the others.
Informal definition for O(…)
• Let , be functions of positive integers.
• Think of as a runtime: positive and increasing in n.

• We say “ is ” if:
for all large enough n,
is at most some constant multiple of .

Here, “constant” means “some number


that doesn’t depend on n.”
Formal definition of O(…)
• Let , be functions of positive integers.
• Think of as a runtime: positive and increasing in n.

• Formally,

“If and only if” “For all”

“There exists”
Ω(…) means a lower bound
• We say “ is ” if, for large enough n, is at least as big
as a constant multiple of .

• Formally,

Switched these!!
Θ(…) means both!
• We say “ is ” iff both:

and
Insertion Sort: running
time
def InsertionSort(A):
for i in range(1,len(A)):
current = A[i]
j = i-1
while j >= 0 and A[j] > current: n-1 iterations
A[j+1] = A[j] of the outer
j -= 1 loop
A[j+1] = current

In the worst case, about n iterations of this inner loop

The running time of insertion sort is .


InsertionSort is an algorithm that
correctly sorts an arbitrary n-element
array in time .

Can we do better?
Can we do better?
• MergeSort: a divide-and-conquer approach

Big problem

Smaller Smaller
problem problem
Recurse! Recurse!

Yet smaller Yet smaller Yet smaller Yet smaller


problem problem problem problem
Divide-And-Conquer
• Divide
• Divide the problem into one or more smaller instances
of the same problem.
• Conquer
• Solve them smaller problems recursively.
• Combine
• Merge/ combine the solutions to solve the original
problem.
Why insertion sort works?
(Recap)
• Say you have a sorted list, 3 4 6 8 , and
another element 5 .

• Insert 5 right after the largest thing that’s still


smaller than 5 . (Aka, right after 4 ).
• Then you get a sorted list:
3 4 5 6 8
• What if you have two
sorted lists? 3 4 6 8 2 5 9 11
MergeSort
6 4 3 8 1 5 2 7

6 4 3 8 1 5 2 7
Recursive magic! Recursive magic!

3 4 6 8 1 2 5 7

MERGE! 1 2 3 4 5 6 7 8
MergeSort Pseudocode
MERGESORT(A):
• n = length(A)
• if n 1: If A has length 1,
It is already sorted!
• return A
Sort the left half
• L = MERGESORT(A[0 : n/2])
Sort the right half
• R = MERGESORT(A[n/2 : n])
• return MERGE(L, R) Merge the two halves
What actually happens?
First, recursively break up the array all the
way down to the base cases

6 4 3 8 1 5 2 7

6 4 3 8 1 5 2 7

6 4 3 8 1 5 2 7

6 4 3 8 1 5 2 7
This array of
length 1 is
sorted!
Then, merge them all back
up!
Sorted sequence!

1 2 3 4 5 6 7 8
Merge!

3 4 6 8 1 2 5 7
Merge! Merge!

4 6 3 8 1 5 2 7
Merge! Merge! Merge! Merge!

6 4 3 8 1 5 2 7
A bunch of sorted lists of length 1 (in the order of the original sequence).
Does it work?
• Yet another job for proof by induction!!!
• Try it yourself.
Assume that n is a power of 2

It’s fast
for convenience.

CLAIM:
MergeSort runs in time

• Proof coming soon.


• But first, how does this compare to InsertionSort?
• Recall InsertionSort ran in time O.
• grows much more slowly than
• grows much more slowly than
Assume that n is a power of 2

Now let’s prove the claim


for convenience.

CLAIM:
MergeSort runs in time
Let’s prove the claim
Size n Level 0

n/2 n/2 Level 1

n/4 n/4 n/4 n/4


Focus on just one of
these sub-problems …
Level t
2t subproblems
n/2t n/2t n/2t n/2t n/2t n/2t
at level t.

(Size 1) Level log(n)


How much work in this sub-
problem?

Time spent MERGE-ing


n/2 t
the two subproblems

+
Time spent within the
n/2 t+1
n/2 t+1
two sub-problems
How much work in this sub-
problem?
Let k=n/2t…

Time spent MERGE-ing


k the two subproblems

+
Time spent within the
k/2 k/2 two sub-problems
How long does it k
take to MERGE? k/2 k/2

Answer: It takes time O(k), since we just walk across the list once.

k/2 k/2

3 4 6 8 1 2 5 7

MERGE! 1 2 3 4 5 6 7 8

k
Recursion tree

Size n

n/2 n/2

n/4 n/4 n/4 n/4


n/2t n/2t n/2t n/2t n/2t n/2t There are O(k) operations
done at this node.

k
k/2 k/2
(Size 1)
Recursion tree

How many operations are done at this level of the


Size n tree? (Just MERGE-ing subproblems).

How about at this level of the tree?


n/2 n/2 (between both n/2-sized problems)

n/4 n/4 This level?


n/4 n/4


This level?
n/2t n/2t n/2t n/2t n/2t n/2t There are O(k) operations
done at this node.

k
k/2 k/2
(Size 1)
Work this out yourself!
Recursion tree Size of
Amount of work
# each
Level problems at this level
problem

Size n
0 1 n O(n)
n/2 n/2
1 2 n/2 O(n)
n/4 n/4 n/4 n/4 2 4 n/4 O(n)
… …
n/2t
n/2t n/2t n/2t n/2t n/2t t 2t n/2t O(n)
… …
log(n)
(Size 1) n 1 O(n)
Total runtime…

• O(n) steps per level, at every level

• log(n) + 1 levels

• O( n log(n) ) total!

That was the claim!


What have we learned?
• MergeSort correctly sorts a list of n integers in time
O(n log(n) ).
• That’s (asymptotically) better than InsertionSort!
Can we do better?
• Any deterministic compare-based sorting algorithm
must make Ω(n log n) compares in the worst-case.
• How to prove this?

• Is there any other way to sort an array efficiently?


QuickSort
QuickSort: another divide-and-conquer approach

• Divide
• Partition the array A[1:n] into two (possibly empty) subarrays A[1:q-
1] (the low side) and A [q+1:n] (the high side)
• Each element in the low side of the partition is <=A[q]
Each element in the high side is of the partition >= A[q].
• Compute the index q of the pivot as part of this partitioning
procedure.
• Conquer
• Recursively sort the subarrays A[1:q-1] and A[q+1:n]
• Combine
• Already sorted
Pseudocode of QuickSort
QUICKSORT(A, p, r)
if p < r
q = PARTITION(A, p, r)
QUICKSORT(A, p, q – 1)
QUICKSORT(A, q+1, r)
PARTITION
PARTITION(A, p, r)
x = A[r]
i = p – 1
for j = p to r – 1
if A[j] <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i + 1] with A[r]
return i + 1
Example of PARTITION

i = -1

7 6 3 5 1 2 4 Pick 4 as a pivot

j = 0 j = 1j = 2
Example of PARTITION

i = -1i = 0

3 6 7 5 1 2 4 Pick 4 as a pivot

j=3j=4
Example of PARTITION

i=0i=1

3 1 7 5 6 2 4 Pick 4 as a pivot

j=5
Example of PARTITION

i=1i=2

3 1 2 5 6 7 4 Pick 4 as a pivot
Example of PARTITION

Low Side High Side

3 1 2 4 6 7 5 Set the pivot in


place
Example of recursive calls
7 6 3 5 1 2 4 Pick 4 as a pivot

Partition on either side of 4


3 1 2 4 6 7 5
Recurse on [312] Recurse on [67] and pick 7
and pick 2 as a 1 2 3 4 5 6 7 as a pivot.
pivot.

1 2 3 4 5 6 7
QuickSort Runtime
Analysis
= The worst-case running time on a problem of size n

• Worst-case partitioning

• Best-case partitioning
Recurrences
• An equation that describes a function in terms of its
value on other, typically smaller, arguments.

• Recursive Case
• Involves the recursive invocation of the function on different
(usually smaller) inputs
• Base Case
• Does not involve a recursive invocation
Algorithmic Recurrences
• A recurrence is algorithmic if, for every sufficiently
large threshold constant , the following two
properties hold,
Solving Recurrences
• Substitution Method
• Guess a solution
• Use mathematical induction to prove the guess
Substitution Method

• Guess

• We need to prove,
• for all,
• For specific choice of and
Substitution Method
• Inductive Hypothesis
• for all and

If cn dominates
Substitution Method
• Base Case

• Assuming

• We get
Solving Recurrences
• Substitution Method
• Guess a solution
• Use mathematical induction to prove the guess

• Making a good guess may be difficult


• Need to be careful about common pitfalls.
Recursion Tree
• Consider the recurrence
Recursion Tree
• Consider the recurrence
Recursion Tree
Recursion Tree
Recursion Tree
• Unbalanced recursion tree
• Estimate the height of the tree
• Estimate the cost from each level
• Estimate the number of leave nodes of the tree
• Estimate the cost from all the leaf nodes over all the
levels

• Example
Master Theorem
• Let’s consider the following recurrence relation,

a>0 b>1 Driving Function


Master Theorem
• Let’s consider the following recurrence relation,

a>0 b>1 Driving Function


Master Theorem


Master Theorem


Master Theorem

• Can we apply case 3?

• Need to satisfy the regularity condition.


Master Theorem

• Regularity condition
Master Theorem

• Applying master theorem (case 2),


MergeSort Runtime
Analysis (Revisit)

• Applying master theorem (case 2),


QuickSort Runtime
Analysis (Revisit)
• Best-case partitioning

• Applying master theorem,

• Worst-case partitioning

• Expanding the recurrence (Rec. tree):


Multiplying Square
Matrices
• A and B are square matrices
• Find out

• Running Time
Can we do better?
Multiplying Square
Matrices
• Divide Assuming

• Conquer
Multiplying Square
Matrices

Θ (1)

𝑛
8𝑇 ( )
2
Multiplying Square
Matrices
• Running Time

• Applying master theorem (case 1),

Can we do better?
Strassen’s Algorithm
• Intuitions,
• Addition is faster than multiplications.

• Replace multiplications with additions


• Remember
Strassen’s Algorithm
• Divide (same as before)
• Conquer
• Perform 10 additions
Strassen’s Algorithm
• Divide (same as before)
• Conquer
• Perform 10 additions,
• Perform 7 multiplications
Strassen’s Algorithm
• Divide (same as before)
• Conquer
• Perform 10 additions,
• Perform 7 multiplications
• Compute with and matrices
Strassen’s Algorithm
Runtime Analysis
• Running Time

• Applying master theorem (case 1),


Reference
• Introduction to Algorithms, CLRS, 4th edition.
• Chapter 2 (Getting Started)
• Section 2.1, 2.3
• Chapter 4 (Divide-and-Conquer)
• Sections 4.1 – 4.5
• Chapter 7 (Quick Sort)
• Sections 7.1 and 7.2

• Additional Resource:
• mastertheorem.pdf

You might also like