1 of 45

CSE 421 Section 4

Divide and Conquer

2 of 45

Writing a Divide and Conquer Algo

3 of 45

Divide and Conquer

  1. Divide instance into subparts
  2. Solve the parts recursively
  3. Conquer by “merging” the answers

The keys to this strategy:

  • Come up with a baseline (usually a brute force algorithm)
  • Your “conquer” step must be faster than brute force!
  • Once you have your algo, write a recurrence for the runtime
    • Your d&c runtime should be BETTER than the baseline runtime

4 of 45

The Strategy (hint: it’s the same as last week!)

  1. Read and Understand the Problem
  2. Generate Examples
  3. Produce a Baseline
  4. Brainstorm and Analyze Possible Algorithms
  5. Write an Algorithm
  6. Show Your Algorithm is Correct
  7. Optimize and Analyze the Run Time

5 of 45

Problem 1 – Maximum Subarray Sum

  •  

6 of 45

1. Read and Understand the Problem

7 of 45

Reminder of the Questions to Ask:

  • What is the input type? (Array? Graph? Integer? Something else?) �

  • What is your return type? (Integer? List?) �

  • Are there any technical terms in the problem you should pay attention to?

8 of 45

Reminder of the Questions to Ask:

  • What is the input type? (Array? Graph? Integer? Something else?) �

  • What is your return type? (Integer? List?) �

  • Are there any technical terms in the problem you should pay attention to?

int[]

9 of 45

Reminder of the Questions to Ask:

  • What is the input type? (Array? Graph? Integer? Something else?) �

  • What is your return type? (Integer? List?) �

  • Are there any technical terms in the problem you should pay attention to?

int[]

int (the largest sum of any subarray)

10 of 45

Reminder of the Questions to Ask:

  • What is the input type? (Array? Graph? Integer? Something else?) �

  • What is your return type? (Integer? List?) �

  • Are there any technical terms in the problem you should pay attention to?

int[]

int (the largest sum of any subarray)

“subarray” means contiguous elements of the array

11 of 45

Key Idea with Divide and Conquer �(and other recursive algorithms)

  • If you identify that you want to use a recursive algorithm paradigm like Divide and Conquer, it’s not enough to just answer those key questions on the previous slide�
  • Since you know you will have recursive calls, you need to be explicit about what those recursive calls are giving you that, when combined together, gives you the solution you’re looking for�
  • You should be clear about the syntax of your recursive calls (i.e. what are the inputs and outputs).

12 of 45

Problem 1.1 – Maximum Subarray Sum

What is the syntax of your recursive calls?

Work through this problem with the people around you, and then we’ll go over it together!

13 of 45

Problem 1.1 – Maximum Subarray Sum

What is the syntax of your recursive calls?

14 of 45

Problem 1.1 – Maximum Subarray Sum

What is the syntax of your recursive calls?

Each recursive call of the form SubarraySumDC(A[], i, j) returns the largest sum of a contiguous subarray of A[], with all elements of the subarray occurring between i and j.

15 of 45

2. Generate Examples

16 of 45

Good examples help with understanding now and testing later!

  • You should generate two or three sample instances and the correct associated outputs. �
  • It’s a good idea to have some “abnormal” examples – consecutive negative numbers, very large negative numbers, only positive numbers, etc.�
  • Note: You should not think of these examples as debugging examples – null or the empty list is not a good example for this step. You can worry about edge cases at the end, once you have the main algorithm idea. You should be focused on the “typical” (not edge) case.

17 of 45

Problem 1.2 – Maximum Subarray Sum

Generate two examples with their associated outputs. Put some effort into these! The more different from each other they are, the more likely you are to catch mistakes later.

Work through generating some examples, and then we’ll go over it together!

18 of 45

Problem 1.2 – Maximum Subarray Sum

Generate two examples with their associated outputs. Put some effort into these! The more different from each other they are, the more likely you are to catch mistakes later.

19 of 45

Problem 1.2 – Maximum Subarray Sum

Generate two examples with their associated outputs. Put some effort into these! The more different from each other they are, the more likely you are to catch mistakes later.

 

20 of 45

3. Come Up with a Baseline

21 of 45

Inefficient (non Divide and Conquer) First Attempt

  • Review: In a time-constrained setting (like a technical interview or an exam) you often want a “baseline” algorithm. This should be an algorithm that you can implement and will give you the right answer, even if it might be slow.

  • When you’re pretty sure you want to use a Divide and Conquer algorithm, this step is very important! You need a (brute force) non Divide and Conquer baseline (with a quick runtime analysis) so you can see whether all the recursive steps of your Divide and Conquer algo are actually saving you any time!

22 of 45

Problem 1.3 – Maximum Subarray Sum

What is the first algorithm that comes to mind for the problem? What would it’s running-time be? (Don’t try to do divide and conquer yet).

23 of 45

Problem 1.3 – Maximum Subarray Sum

  •  

24 of 45

Problem 1.3 – Maximum Subarray Sum

  •  

25 of 45

Problem 1.3 – Maximum Subarray Sum

function BetterBaseline(A[1..n])

bestSum ← −∞

for i from 1 to n do // i represents start index

sum ← 0

for j from i to n do // j represents end index

sum += A[j]

if sum > bestSum then

bestSum ← sum

if bestSum < 0 then // handle all negative entries case

return 0 // empty subarray must be best here

return bestSum

26 of 45

Problem 1.3 – Maximum Subarray Sum

function BetterBaseline(A[1..n])

bestSum ← −∞

for i from 1 to n do // i represents start index

sum ← 0

for j from i to n do // j represents end index

sum += A[j]

if sum > bestSum then

bestSum ← sum

if bestSum < 0 then // handle all negative entries case

return 0 // empty subarray must be best here

return bestSum

 

27 of 45

4. Brainstorm and Analyze �Possible Algorithms

28 of 45

Think about How to Divide and Conquer

  • Questions to help you brainstorm out your Divide and Conquer algo:
    • How do you want to split up the problem?
    • What is returned from the recursive calls? (hint: look back at part 1)
    • Imagine you have the answers from those recursive calls; �what is there still to handle?

  • When you have time, it’s a good idea to try to run through your idea with some of the examples you came up with earlier, and see whether you get the correct output (especially as you try to transition from your brainstorming to formalizing your algorithm)

29 of 45

Problem 1.4 – Maximum Subarray Sum

For each call SubarraySumDC(A[1..n]) answer these questions:

How do you want to split up the problem?

What is returned from the recursive calls?

Imagine you have the answers from those recursive calls; what is there still to handle?

30 of 45

Problem 1.4 – Maximum Subarray Sum

For each call SubarraySumDC(A[1..n]) answer these questions:

How do you want to split up the problem?

What is returned from the recursive calls?

Imagine you have the answers from those recursive calls; what is there still to handle?

Let’s just split the array in half! Make two recursive calls, one for each half (we don’t know where the subarray is, so we’ll have to make both).

31 of 45

Problem 1.4 – Maximum Subarray Sum

For each call SubarraySumDC(A[1..n]) answer these questions:

How do you want to split up the problem?

What is returned from the recursive calls?

Imagine you have the answers from those recursive calls; what is there still to handle?

Let’s just split the array in half! Make two recursive calls, one for each half (we don’t know where the subarray is, so we’ll have to make both).

Each recursive call will return the sum of the largest subarray among half the elements, either 1,…n/2 or n/2+1,…n.

32 of 45

Problem 1.4 – Maximum Subarray Sum

For each call SubarraySumDC(A[1..n]) answer these questions:

How do you want to split up the problem?

What is returned from the recursive calls?

Imagine you have the answers from those recursive calls; what is there still to handle?

Let’s just split the array in half! Make two recursive calls, one for each half (we don’t know where the subarray is, so we’ll have to make both).

Each recursive call will return the sum of the largest subarray among half the elements, either 1,…n/2 or n/2+1,…n.

If the subarray “crosses” from one side to the other (i.e., includes both n/2 and n/2+1), it hasn’t been checked yet. We still need to discover and check those.

33 of 45

5. Write an Algorithm

34 of 45

Translate the brainstorm into an algorithm!

  • We need to take those ideas we were just noodling on and write them into an algorithm!
  • We can start with formalizing our ideas from earlier, but then we still need to figure out how to deal with those subarrays that cross from one half to the other…

35 of 45

Translate the brainstorm into an algorithm!

  •  

36 of 45

Translate the brainstorm into an algorithm!

  •  

37 of 45

Problem 1.5 – Maximum Subarray Sum

On whiteboard (see solutions)

38 of 45

6. Show Your Algorithm is Correct

39 of 45

Problem 1.6 – Maximum Subarray Sum

Write a proof of correctness.

Work on this proof with the people around you, and then we’ll go over it together!

40 of 45

Problem 1.6 – Maximum Subarray Sum

 

41 of 45

Problem 1.6 – Maximum Subarray Sum

 

42 of 45

7. Optimize and Analyze the Run Time

43 of 45

Problem 1.7 – Maximum Subarray Sum

Write the big-O of your code and justify the running time with a few sentences.

44 of 45

Problem 1.7 – Maximum Subarray Sum

Write the big-O of your code and justify the running time with a few sentences.

 

45 of 45

That’s All, Folks!

Thanks for coming to section this week!

Any questions?