Recurrences
CSE 332 - Section 3
Part 1: Recurrence Relations
Recurrence Relations Overview
OR
“Divide & Conquer”
“Chip & Conquer”
Recurrence Relations Examples
foo(L) { // n = L.size
if (L.size <= 1) {
return 1;
}
L.remove(0); // n = n-1
return foo(L) + foo(L);
}
a = 2
b = 1
OR
bar(A, start, n) {
if (n-start <= 1) {
return 1;
}
return 2*bar(A, start, n/2);
}
a = 1
b = 2
Problem 0a
1 f(stack) { // stack.size = n
2 if (stack.size == 0) {
3 return 0
4 }
5 stack.pop // stack.size --
6 return 2*f(stack)+1
7 }
Find a recurrence T(n) modelling the worst-case runtime complexity of f(n)
n ≤ 0
?
a = 1 since we only make one recursive call
b = 1 since we always reduce input size by 1
constant
constant
constant, which we can denote as c1
Recurrence relation forms:
Problem 0b
1 g(A, start, n) {
2 if n ≤ 10000 {
3 return 1000
4 }
5
6 if (g(A, start, n/3) > 5) {
7 for (int i=0; i<n; i++) {
8 println("Yay")
9 }
10 return 5*g(A, start, n/3)
11 } else {
12 for (int i=0; i<n*n; i++) {
13 println("Yay")
14 }
15 return 4*g(A, start, n/3)
16 }
Find a recurrence T(n) modelling the worst-case runtime complexity of f(n)
n ≤ 10000
a = 2
b = 3
c1*n + c2
Recurrence relation forms:
Tree Method Overview
Big Idea: T(n/b)
…
…
…
…
…
c
Red box represents a problem instance
Blue value represents time spent at that level of recursion
…
…
…
Asymptotically, these never matter!
Big Idea: T(n - b)
Red box represents a problem instance
Blue value represents time spent at that level of recursion
n
f(n)
n - b
n - b
n - 2b
n - 2b
n - 2b
n - 2b
…
…
…
…
…
x
x
x
…
x
x
f(n-b)
f(n-b)
f(n-2b)
f(n-2b)
f(n-2b)
f(n-2b)
c
c
c
c
c
≈ n/b levels
Asymptotically, these never matter!
⇒ ai f(n - bi)
work per level
Q1(a) Tree Method Example
…
…
…
…
…
Red box represents a problem instance
Blue value represents time spent at that level of recursion
Q1(a) Solving the Summation
Your Turn!
Try problems 1b-1f
Q1(b) Base Case Doesn’t Matter!
…
…
…
…
…
Red box represents a problem instance
Blue value represents time spent at that level of recursion
…
…
Q1(b) Solving the Summation
Q1(c) Constants for f(n) Don’t Matter!
…
…
…
…
…
Red box represents a problem instance
Blue value represents time spent at that level of recursion
…
…
Q(1c) Solving the Summation
Q1(d) Branching Factor (a) Matters!
…
…
…
…
…
Red box represents a problem instance
Blue value represents time spent at that level of recursion
…
Q(1d) Solving the Summation
can move the n using the constant multiple rule
multiplied by -2 and distributed our n
Q1(e) Reduction Factor (/b) Does Matter!
…
…
…
…
…
Red box represents a problem instance
Blue value represents time spent at that level of recursion
…
…
Q(1e) Solving the Summation
can move the n using the constant multiple rule
This is a geometric series with a ratio < 1, so it converges to a constant!
Q1(f): Tree method
n
Work: 1
n-2
n-2
n-4
n-4
n-4
n-4
…
…
…
…
1
1
1
…
1
1
1
1
1
1
1
1
1
1
1
1
1
≈ n/2 levels
⇒ 2i work per level
#children
#levels
work
Q1(f): Solving the Summation
Note: formula like this will be provided for exams
Reduction Constant (-b) Matters!
1
1
Left/top represents -1 case
Right/bottom represents -2 case
n
1
n-1 or n-2
n-1 or n-2
n-2 or n-4
n-2 or n-4
n-2 or n-4
n-2 or n-4
…
…
…
…
1
1
1
…
1
1
1
1
1
1
1
1
1
1
1
≈ n levels for -1
≈ n/2 levels for -2
⇒ 2i
work per level for both cases
Hint: Use the Finite Geometric Series (#7 on Math Identities) to solve these summations!
General Advice
Recursive Running Times - Guidance
Only differences between divide and conquer cases highlighted in yellow
Putting it All Together
Problem 2(a)
(a) Find a recurrence T(n) modeling the worst-case runtime complexity of f(n).
1 f(L, start, n) {
2 if (n - start <= 1) {
3 return 0
4 }
5 int res = f(L, start, n/2)
6 for (int i=0; i<n; i++) {
7 result *= 4
8 }
9 return res + f(L, start, n/2)
10 }
1 f(L, start, j) { //n = j - start
2 if (j - start <= 1) {
3 return 0
4 }
5 int res = f(L, start, n/2)
6 for (int i=0; i<j; i++) {
7 result *= 4
8 }
9 return res + f(L, start, j/2)
10 }
Problem 2(a)
(a) Find a recurrence T(n) modeling the worst-case runtime complexity of f(n).
1 f(L, start, j) { //n = j - start
2 if (j - start <= 1) {
3 return 0
4 }
5 int res = f(L, start, n/2)
6 for (int i=0; i<j; i++) {
7 result *= 4
8 }
9 return res + f(L, start, j/2)
10 }
Problem 2(b)
(b) Find a closed form to your answer for (a).
Our first call to T(n)
Our first call to T(n)
Input: n
Our first call to T(n)
Input: n
Work: c2*n + c1
Input: n/2
Input:
n/2
“2T(...)” = 2 recursive calls
Input: n
Work: c2*n + c1
Input: n/2
Input: n/2
Input: n
Work: c2*n + c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/2
Work: c2*(n/2)+c1
Input: n
Work: c2*n + c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/4
Input: n/4
Input: n/4
Input: n/4
Input: n
Work: c2*n + c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n
Work: c2*n + c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n
Work: c2*n + c1
Input: 1
Input: 1
Input: 1
Input: 1
Input: n/2
Work: c2*(n/2)+c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n
Work: c2*n + c1
Input: 1
Work: c0
Input: 1
Work: c0
Input: 1
Work: c0
Input: 1
Work: c0
Input: n/2
Work: c2*(n/2)+c1
Input: n/2
Work: c2*(n/2)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n/4
Work: c2*(n/4)+c1
Input: n
Work: c2*n + c1
Input: 1
Work: c0
Input: 1
Work: c0
Input: 1
Work: c0
Input: 1
Work: c0
Since we’re in /b case:
With a, b, and f(n) plugged in:
Thank You!