0% found this document useful (0 votes)
88 views83 pages

CS2040S Data Structures and Algorithms: Welcome!

This document describes a tutorial allocation problem and proposes a solution using binary search. It begins by explaining the problem - students want certain tutorials, each tutorial should have less than 18 students, and the goal is to determine the minimum number of tutorials needed. It then notes that a greedy approach will not work. The key observation is made that the number of students in the biggest tutorial decreases as more tutorials are opened. This means the problem exhibits a monotonic property with respect to the number of tutorials. Finally, the document proposes using binary search to efficiently find the minimum number of tutorials needed, defining a function MaxStudents(x) to represent the number of students in the most crowded tutorial given x tutorials.

Uploaded by

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

CS2040S Data Structures and Algorithms: Welcome!

This document describes a tutorial allocation problem and proposes a solution using binary search. It begins by explaining the problem - students want certain tutorials, each tutorial should have less than 18 students, and the goal is to determine the minimum number of tutorials needed. It then notes that a greedy approach will not work. The key observation is made that the number of students in the biggest tutorial decreases as more tutorials are opened. This means the problem exhibits a monotonic property with respect to the number of tutorials. Finally, the document proposes using binary search to efficiently find the minimum number of tutorials needed, defining a function MaxStudents(x) to represent the number of students in the most crowded tutorial given x tutorials.

Uploaded by

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

CS2040S

Data Structures and Algorithms

Welcome!

is open
How to Search!

Algorithm Analysis
– Big-O Notation
– Model of computation

Searching

Peak Finding
– 1-dimension
– 2-dimensions
Admin: Tutorial/Recitations

Recitation Allocation Appeals:


– Almost done
Please respond to
– 4 students left emails requesting your
schedule.

Tutorial Allocation Appeals:


– In progress
– Hopefully done by tomorrow.

Both start next week (Week 3)


Puzzle (2?) of the Week (Contest)
Treasure Island
You have found a treasure chest!
It has a lot of locks on it!

You need ALL the correct keys to


open the chest.

Find the right set of keys to win!

Image Credit: Britannica


Puzzle of the Week (Contest)
Treasure Island

You choose a set of keys.

You can test whether all the good


keys are in the set (and possibly
some extra keys). If even one bad key
is in the set, then it fails.

Goal: identify exactly the good keys.

Image Credit: Britannica


Puzzle of the Week (Contest)
Treasure Island

You choose a set of keys.

You can test whether all the good


keys are in the set (and possibly
some extra keys). If even one bad key
is in the set, then it fails.

Goal: identify exactly the good keys.


Puzzle of the Week (Contest)
Treasure Island

You choose a set of keys.

You can test whether all the good


keys are in the set (and possibly
some extra keys). If even one bad key
is in the set, then it fails.

Goal: identify exactly the good keys.


FAIL
Puzzle of the Week (Contest)
Treasure Island

You choose a set of keys.

You can test whether all the good


keys are in the set (and possibly
some extra keys). If even one bad key
is in the set, then it fails.

Goal: identify exactly the good keys.


SUCCEED
Puzzle of the Week (Contest)
Treasure Island

You choose a set of keys.

You can test whether all the good


keys are in the set (and possibly
some extra keys). If even one bad key
is in the set, then it fails.

Goal: identify exactly the good keys.


SUCCEED and OPEN
Puzzle of the Week (Contest)
Treasure Island
Two goals:
• Minimize number of tries.
• Minimize total number of keys tried.

Image Credit: Britannica


Puzzle of the Week (Contest)
Treasure Island

For example:
• Total number of keys = 1024
• Number of correct keys = 17

Required number of attempts: >= 122

Image Credit: Britannica


Announcements

Competition:
Find the keys!

Open on Coursemology for one week:


• Optional.
• Write a program to implement your best treasure finding strategy.
• We will test it on various treasure chests.
• Fewest tries / fewest keys wins!
• (And a small bonus for participating.)
How to Search!

Algorithm Analysis
– Big-O Notation
– Model of computation

Searching

Peak Finding
– 1-dimension
– 2-dimensions
Last time…
Binary Search
• Simple, ubiquitous algorithm.
• Surprisingly easy to add bugs.
• Some ideas for avoiding bugs:
• Problem specification
• Preconditions
• Postconditions
• Invariants / loop invariants
• Validate (when feasible)
Binary Search
Sorted array: A[0..n-1]

Not just for searching arrays:


– Assume a complicated function:
int complicatedFunction(int s)
– Assume the function is always increasing:
complicatedFunction(i) < complicatedFunction(i+1)
– Find the minimum value j such that:
complicatedFunction(j) > 100
A problem…
Tutorial allocation
A problem…
Tutorial allocation
T1

T2

T3
Tutorials
(in order T4
of tutor
preference)
T5

T6

T7

T8
A problem…
Tutorial allocation
T1 Students want
certain tutorials.
T2

T3
Tutorials
(in order T4
of tutor
preference)
T5

T6

T7

T8
A problem…
Tutorial allocation
T1 Students want
certain tutorials.
T2

T3 We want each
Tutorials tutorial to have
(in order T4
of tutor < 18 students..
preference)
T5

T6

T7

T8
A problem…
Tutorial allocation
T1 Students want
certain tutorials.
T2

T3 We want each
Tutorials tutorial to have
(in order T4
of tutor < 18 students..
preference)
T5

T6 How many tutorials


do we need to run?
T7

T8
A problem…
Tutorial allocation
T1 Students want
certain tutorials.
T2

T3 We want each
Tutorials tutorial to have
(in order T4
of tutor < 18 students..
preference)
T5

T6 How many tutorials


do we need to run?
T7

T8
A problem…
Tutorial allocation
T1 Can we do
greedy allocation?
T2
First, fill T1.
T3 Then fill T2.
Tutorials Then fill T3.
(in order T4 …
of tutor
preference) Stop when all
T5 students are
allocated
T6

T7

T8 or on Zoom.
A problem…
Tutorial allocation
T1 Can we do
greedy allocation?
T2
NO
T3
Tutorials Assume max
(in order T4 tutorial size is 1.
of tutor
preference)
T5 Assign student 1 to
tutorial 1.
T6
Now we need all 8
T7 tutorials.
T8
A problem…
Tutorial allocation
T1 Can we do
greedy allocation?
T2
NO
T3
Tutorials Assume max
(in order T4 tutorial size is 1.
of tutor
preference)
T5 Assign student 1 to
tutorial 1.
T6
Now one student
T7 has no feasible
allocation!
T8
A problem… Example of decomposing
an algorithm into parts!
Tutorial allocation
T1 Assume we can
solve allocation
T2 problem:

T3 Given a fixed set of


tutorials and a fixed
Tutorials
(in order T4 set of students, find
of tutor an allocation where
preference)
T5 every student has a
slot.
T6
Assumptions:
• may be > 18 students in
T7 a slot!
• minimizes max students
T8 in a slot.
A problem…
Tutorial allocation
T1 How to find
minimum number
T2 of tutorials that we
need to open to
T3 ensure: no tutorial
Tutorials has more than 18
(in order T4 students.
of tutor
preference)
T5

T6

T7

T8
A problem…
Tutorial allocation
T1 Observation:

T2 Number of
students in
T3 BIGGEST tutorial
Tutorials only decreases as
(in order T4 number of tutorials
of tutor
preference) increases.
T5

T6 Monotonic
function of
T7 number of
tutorials!
T8
A problem…
Tutorial allocation
T1
Monotonic
T2
function of
number of
T3
tutorials!
Tutorials
(in order T4
of tutor
preference)
T5

T6 Binary Search

T7

T8
A problem… T1

T2

Tutorial allocation T3

T4

Solution: T5

T6
Binary Search
T7

Define:
T8

MaxStudents(x) = number of students in most crowded tutorial,


if we offer x tutorials.
Binary Search
T1

T2

T3

T
4

MaxStudents(x) = number of students in most T5

crowded tutorial, T
6

if we offer x tutorials. T7

Search(n) T
8

begin = 0
end = n-1
while begin < end do:
mid = begin + (end-begin)/2;
if MaxStudents(mid) <= 18 then
end = mid
else begin = mid+1
return begin
Binary Search
Sorted array: A[0..n-1]

Not just for searching arrays:


– Assume a complicated function:
int complicatedFunction(int s)
– Assume the function is always increasing:
complicatedFunction(i) < complicatedFunction(i+1)
– Find the minimum value j such that:
complicatedFunction(j) > 100
How to Search!

Algorithm Analysis
– Big-O Notation
– Model of computation

Searching

Peak Finding
– 1-dimension
– 2-dimensions
Peak Finding
Global
Maximum
Input: Some function f(x)

f(x)

x
local maximum
Peak Finding
Global Maximum for Optimization problems:
– Find a good solution to a problem.
– Find a design that uses less energy.
– Find a way to make more money.
– Find a good scenic viewpoint.
– Etc.
Why local maximum?
– Finds a good enough solution.
– Local maxima are close to the global maximum?
– Much, much faster.
Global Maximum
Input: Array A[0..n-1]
Output: global maximum element in A
How long to find a global maximum?
Input: Array A[0..n-1]
Output: maximum element in A

1. O(log n)
2. O(n)
3. O(n log n)
4. O(n2)
5. O(2n)

is open
Global Maximum

Unsorted array: A[0..n-1]

FindMax(A,n)
max = A[1]
for i = 1 to n do:
if (A[i]>max) then max=A[i]

Too slow!
Time Complexity: O(n)
Peak (Local Maximum) Finding

Input: Some function f(x)

f(x)

x
Output: A local maximum
Peak Finding

Input: Some function array A[0..n-1]

Output: a local maximum in A


A[i-1]≤ A[i] and A[i+1]≤ A[i]

Assume that
A[-1] = A[n] = -MAX_INT
Peak Finding: Algorithm 1

Input: Some array A[0..n-1]

FindPeak
– Start from A[1]
– Examine every element
– Stop when you find a peak.
Peak Finding: Algorithm 1

Input: Some array A[0..n-1]

FindPeak
– Start from A[1]
– Examine every element
– Stop when you find a peak.
Peak Finding: Algorithm 1

Input: Some array A[0..n-1]

FindPeak
– Start from A[1]
– Examine every element
– Stop when you find a peak.
Peak Finding: Algorithm 1

Input: Some array A[0..n-1]

Running time: n

Simple improvement?
Peak Finding: Algorithm 1

Input: Some array A[0..n-1]

Start in the middle!

Worst-case: n/2
Peak Finding: Algorithm 2
Reduce-and-Conquer

Start in the middle


5 < 6? OK
6 > 23? NO
Recurse!
Peak Finding: Algorithm 2
Reduce-and-Conquer
Peak Finding: Algorithm 2
Divide-and-Conquer
Peak Finding: Algorithm 2
Divide-and-Conquer

We found a peak!
Peak Finding

Input: Some array A[0..n-1]

FindPeak(A, n)
if A[n/2] is a peak then return n/2
else if A[n/2+1] > A[n/2] then
Search for peak in right half.
else if A[n/2–1] > A[n/2] then
Search for peak in left half.
Peak Finding

Input: Some array A[0..n-1]

FindPeak(A, n)
if A[n/2] is a peak then return n/2
else if A[n/2+1] > A[n/2] then
FindPeak (A[n/2+1..n], n/2)
else if A[n/2–1] > A[n/2] then
FindPeak (A[1..n/2-1], n/2)
Peak Finding
Is this correct? is open

FindPeak(A, n) Should this be >=?

if A[n/2] is a peak then return n/2


else if A[n/2+1] > A[n/2] then
FindPeak (A[n/2+1..n], n/2)
else if A[n/2–1] > A[n/2] then Missing else
condition?
FindPeak (A[1..n/2-1], n/2)
Peak Finding
Should this be >=? No: recurse on the larger half.

FindPeak(A, n)
if A[n/2] is a peak then return n/2
else if A[n/2+1] > A[n/2] then
FindPeak (A[n/2+1..n], n/2)
else if A[n/2–1] > A[n/2] then
FindPeak (A[1..n/2-1], n/2)
Peak Finding
Missing else condition? No: else we have found a peak!

FindPeak(A, n)
if A[n/2] is a peak then return n/2
else if A[n/2+1] > A[n/2] then
FindPeak (A[n/2+1..n], n/2)
else if A[n/2–1] > A[n/2] then
FindPeak (A[1..n/2-1], n/2)
Peak Finding
Missing else condition? No: else we have found a peak!

FindPeak(A, n)
if A[n/2+1] > A[n/2] then
FindPeak (A[n/2+1..n], n/2)
else if A[n/2–1] > A[n/2] then
FindPeak (A[1..n/2-1], n/2)
else A[n/2] is a peak; return n/2
Peak Finding
Key property è invariant:
If we recurse in the right half, then there exists a peak
in the right half.
Peak Finding
Key property:
– If we recurse in the right half, then there exists a
peak in the right half.
Explanation:
– Assume there is “no peak” in the right half.
– Given: A[middle] < A[middle + 1]
– Since no peaks, A[middle+1] < A[middle+2]
– Since no peaks, A[middle+2] < A[middle+3]
– …
– Since no peaks, A[n-1] < A[n] PEAK!!
Peak Finding
Recurse on right half, since 23 > 6.
Assume no peaks in right half.
Peak Finding
Key property:
– If we recurse in the right half, then there exists a
peak in the right half.
Explanation:
– Assume there is “no peak” in the right half.
– Because we recursed right: A[middle] < A[middle + 1]
– Since no peaks, A[middle+1] < A[middle+2]
– Since no peaks, A[middle+2] < A[middle+3]
– …
– Since no peaks, A[n-1] < A[n] PEAK!!
Peak Finding
Key property:
– If we recurse in the right half, then there exists a
peak in the right half.
Induction:
– Assume there is “no peak” in the right half.
– Inductive hypothesis:
For all (j > middle): A[j-1] < j
Peak Finding
Key property:
– If we recurse in the right half, then there exists a
peak in the right half.
Induction:
– Assume there is “no peak” in the right half.
– Inductive hypothesis:
For all (j > middle): A[j-1] < j
– Base case: j = middle+1
Because we recursed on the right half, we know that
A[middle] < A[middle + 1].
Peak Finding
Key property:
– If we recurse in the right half, then there exists a
peak in the right half.
Induction:
– Assume there is “no peak” in the right half.
– Inductive hypothesis:
For all (j > middle): A[j-1] < j
– Induction: j > middle+1
By induction, A[j-2] <= A[j-1].
If A[j-1] >= A[j], then A[j-1] is a peak è contradiction.
Peak Finding
Key property:
– If we recurse in the right half, then there exists a
peak in the right half.
Induction:
– Assume there is “no peak” in the right half.
– Inductive hypothesis:
For all (j > middle): A[j-1] < j
– Conclusion: A[n-2] < A[n-1]
è A[n-1] is a peak è contradiction.
Key Invariants:
Correctness:

There exists a peak in the range [begin, end].

begin end
Key Invariants:
Is this good enough to prove the algorithm works?

There exists a peak in the range [begin, end].

begin end

is open
Key Invariants:
Not good enough to prove the algorithm works!

There exists a peak in the range [begin, end].

begin end
Key Invariants:
Not good enough to prove the algorithm works!

There exists a peak in the range [begin, end].

begin end
Key Invariants:
Not good enough to prove the algorithm works!

There exists a peak in the range [begin, end].

Run peak finding algorithm è returns 15


Key Invariants:
Not good enough to prove the algorithm works!

There exists a peak in the range [begin, end].

Run peak finding algorithm è returns 15


But 15 is NOT a peak! If the recursive call finds a
peak, is it still a peak after
the recursive call returns?
Key Invariants:
Correctness:

1. There exists a peak in the range [begin, end].

2. Every peak in[begin, end] is a peak in [1, n].


Peak Finding
Key property:
– If we recurse in the right half, then every peak in
the right half is a peak in the array.
Proof: use the invariant (inductively)
– Immediately true for every peak that is not at a
boundary in new array. Recurse here

Non-border peak
Peak Finding
Key property:
– If we recurse in the right half, then every peak in
the right half is a peak in the array.
Proof: use the invariant (inductively)
– True by invariant for current array.
Recurse here

Invariant says this peak is really a peak.


Peak Finding
Key property:
– If we recurse in the right half, then every peak in
the right half is a peak in the array.
Proof: use the invariant (inductively)
– If 45 is a peak in the new array but not the old
array, then we would not recurse on the right side.
è If left edge is a peak in new array, then it is a peak.

If 45 is a peak in right half and we recurse on right half, then it is a peak.


Key Invariants:
Correctness:

1. There exists a peak in the range [begin, end].

2. Every peak in[begin, end] is a peak in [1, n].


Peak Finding
is open

Running time?

FindPeak(A, n)
if A[n/2] is a peak then return n/2
else if A[n/2+1] > A[n/2] then
Search for peak in right half.
else if A[n/2–1] > A[n/2] then
Search for peak in left half.
Peak Finding
Running time: Time for comparing
A[n/2] with neighbors
Time to find a peak in
an array of size n Recursion

T(n) = T(n/2) + q(1)


Peak Finding
Running time: Time for comparing
A[n/2] with neighbors
Time to find a peak in
an array of size n Recursion

T(n) = T(n/2) + q(1)

Unrolling the recurrence:


T(n) = q(1) + q(1) +…+ q(1) = O(log n)
Peak Finding
Rule:
Unrolling the recurrence: T(X) = T(X/2) + O(1)
T(n) = T(n/2) + q(1)
= T(n/4) + q(1) + q(1)
= T(n/8) + q(1) + q(1) + q(1)


= T(1) + q(1) +…+ q(1) =
= q(1) + q(1) +…+ q(1) =
Peak Finding
Rule:
Unrolling the recurrence: T(X) = T(X/2) + O(1)
T(n) = T(n/2) + q(1)
= T(n/4) + q(1) + q(1) Number
of times
= T(n/8) + q(1) + q(1) + q(1) you can
divide n
… by 2 until
you reach 1.

= T(1) + q(1) +…+ q(1) =
= q(1) + q(1) +…+ q(1) =
Peak Finding
How many times can you divide a number
n in half before you reach 1?

2 x 2 x…x 2 = 2log(n) = n
log(n)

Note: I always assume log = log2


O(log2 n) = O(log n)
Peak Finding
Running time: Time for comparing
A[n/2] with neighbors
Time to find a peak in
an array of size n Recursion

T(n) = T(n/2) + q(1)

Unrolling the recurrence:


T(n) = q(1) + q(1) +…+ q(1) = O(log n)

log(n)
Peak Finding

Input: Some array A[0..n-1]

Output: a local maximum in A


A[i-1]≤ A[i] and A[i+1]≤ A[i]

Assume that
A[-1] = A[n] = -MAX_INT
Steep Peaks

Input: Some array A[0..n-1]

Output: a local maximum in A


A[i-1]< A[i] and A[i+1]< A[i]

Assume that
A[-1] = A[n] = -MAX_INT
Steep Peaks
is open

Input: Some array A[0..n-1]

Output: a local maximum in A


A[i-1]< A[i] and A[i+1]< A[i]

Can we find steep peaks efficiently (in O(log n)


time) using the same approach?

You might also like