$ \def\compare{ {\mathrm{compare}} } \def\swap{ {\mathrm{swap}} } \def\sort{ {\mathrm{sort}} } \def\insert{ {\mathrm{insert}} } \def\true{ {\mathrm{true}} } \def\false{ {\mathrm{false}} } \def\BubbleSort{ {\mathrm{BubbleSort}} } \def\SelectionSort{ {\mathrm{SelectionSort}} } \def\Merge{ {\mathrm{Merge}} } \def\MergeSort{ {\mathrm{MergeSort}} } \def\QuickSort{ {\mathrm{QuickSort}} } \def\Split{ {\mathrm{Split}} } \def\Multiply{ {\mathrm{Multiply}} } \def\Add{ {\mathrm{Add}} } $
The “Master Theorem”
Given recurrence $T(n) = a T(n / b) + f(n)$
Define $c = \log_b a$
Three cases:
In formal statement we have
In practice, might have
The conclusion of the theorem still holds in this case!
$T(n) = a T(n / b) + f(n)$
BinarySearch(a, val, i, j):
if j = i then return false
if j - i = 1 then return (a[i] = val)
m <- (j + i) / 2
if a[m] > val then
return BinarySearch(a, val, i, m)
else
return BinarySearch(a, val, m, j)
endif
$T(n) = a T(n / b) + f(n)$
MergeSort(a, i, j):
if j - i = 1 then
return
endif
m <- (i + j) / 2
MergeSort(a,i,m)
MergeSort(a,m,j)
Merge(a,i,m,j)
Goal. Pick day $b$ to buy and day $s$ to sell to maximize profit.
Input. Array $a$ of size $n$
Output. Indices $b$ (buy) and $s$ (sell) with $1 \leq b \leq s \leq n$ that maximize profit
Devise a procedure to determine max profit in time $O(n^2)$.
Question. Can we compute maximum profit faster?
Array $a$ of size $n$, midpoint $m = n / 2$
To find the maximum profit for split halves:
Maximum profit is $a[s] - a[b]$.
# find maximum profit achievable for b, s
# satisfying i <= b <= s < j
MaxProfit(a, i, j):
if j - i = 1 then return 0
m <- (i + j) / 2
left <- MaxProfit(a, i, m)
right <- MaxProfit(a, m, j)
min <- FindMin(a, i, m)
max <- FindMax(a, m, j)
return Max(left, right, max - min)
MaxProfit([1, 3, 2, 4], 1, 5)
Claim. MaxProfit(a, i, j)
returns the maximum value of $a[s] - a[b]$ over all $s, b$ satisfying $i \leq b \leq s < j$.
Proof. Argue by induction on $n = j - i =$ size of the call.
MaxProfit(a, i, j):
if j - i = 1 then return 0
...
Base case. $n = 1$.
MaxProfit(a, i, j):
...
left <- MaxProfit(a, i, m), right <- MaxProfit(a, m, j)
min <- FindMin(a, i, m), max <- FindMax(a, m, j)
return Max(left, right, max - min)
Claim. MaxProfit(a, i, j)
returns the maximum value of $a[s] - a[b]$ over all $s, b$ satisfying $i \leq b \leq s < j$.
Three possible cases…
MaxProfit(a, i, j):
...
left <- MaxProfit(a, i, m), right <- MaxProfit(a, m, j)
min <- FindMin(a, i, m), max <- FindMax(a, m, j)
return Max(left, right, max - min)
Claim. MaxProfit(a, i, j)
returns the maximum value of $a[s] - a[b]$ over all $s, b$ satisfying $i \leq b \leq s < j$.
Inductive hypothesis. Claim holds for all sizes $< n$.
Inductive step. Must show claim holds for size $n$.
left
is max profit in a[i..m-1]
right
is max profit in a[m..j-1]
max - min
is max profit with $b < m \leq s$$T(n) = a T(n / b) + f(n)$
# find maximum profit achievable for b, s
# satisfying i <= b <= s < j
MaxProfit(a, i, j):
if j - i = 1 then return 0
m <- (i + j) / 2
left <- MaxProfit(a, i, m)
right <- MaxProfit(a, m, j)
min <- FindMin(a, i, m)
max <- FindMax(a, m, j)
return Max(left, right, max - min)
Given recurrence $T(n) = a T(n / b) + f(n)$
Define $c = \log_b a$
Three cases:
Modify the code to return the indices b
and s
that maximize profit.
# find maximum profit achievable for b, s
# satisfying i <= b <= s < j
MaxProfit(a, i, j):
if j - i = 1 then return 0
m <- (i + j) / 2
left <- MaxProfit(a, i, m)
right <- MaxProfit(a, m, j)
min <- FindMin(a, i, m)
max <- FindMax(a, m, j)
return Max(left, right, max - min)